Jawaban:
Saya akan menulis penjelasan saya sendiri tetapi artikel Wikipedia ini cukup merangkumnya.
Inilah konsep dasarnya:
Copy-on-write (kadang-kadang disebut sebagai "SAP") adalah strategi optimasi yang digunakan dalam pemrograman komputer. Ide dasarnya adalah bahwa jika banyak penelepon meminta sumber daya yang awalnya tidak dapat dibedakan, Anda dapat memberi mereka petunjuk ke sumber daya yang sama. Fungsi ini dapat dipertahankan sampai penelepon mencoba untuk memodifikasi "salinan" dari sumber daya, di mana titik salinan pribadi yang sebenarnya dibuat untuk mencegah perubahan menjadi terlihat oleh orang lain. Semua ini terjadi secara transparan kepada penelepon. Keuntungan utama adalah bahwa jika penelepon tidak pernah melakukan modifikasi, tidak ada salinan pribadi yang perlu dibuat.
Juga di sini adalah aplikasi penggunaan SAP yang umum:
Konsep COW juga digunakan dalam pemeliharaan snapshot instan pada server database seperti Microsoft SQL Server 2005. Snapshots instan mempertahankan tampilan statis database dengan menyimpan salinan data pra-modifikasi ketika data underlaying diperbarui. Snapshots instan digunakan untuk menguji penggunaan atau laporan yang bergantung pada momen dan tidak boleh digunakan untuk mengganti cadangan.
clone()
untuk mengimplementasikan fork()
- memori proses induk adalah COWed untuk anak.
"Salin saat menulis" artinya kurang lebih seperti: setiap orang memiliki satu salinan bersama dari data yang sama sampai ditulis , dan kemudian salinan dibuat. Biasanya, copy-on-write digunakan untuk menyelesaikan berbagai masalah konkurensi. Di ZFS , misalnya, blok data pada disk dialokasikan copy-on-write; selama tidak ada perubahan, Anda tetap menyimpan blok aslinya; perubahan hanya mengubah blok yang terpengaruh. Ini berarti jumlah minimum blok baru dialokasikan.
Perubahan-perubahan ini juga biasanya diimplementasikan menjadi transaksional , yaitu mereka memiliki sifat ACID . Ini menghilangkan beberapa masalah konkurensi, karena dengan demikian Anda dijamin bahwa semua pembaruan bersifat atomik.
A
. Proses 1
, 2
, 3
, 4
masing-masing inginkan untuk membuat salinan itu dan mulai membacanya, dalam "Copy pada menulis" sistem tidak ada yang disalin namun semuanya masih membaca A
. Sekarang proses 3
ingin membuat perubahan pada salinannya A
, proses 3
sekarang akan benar-benar membuat salinan A
dan membuat blok data baru yang disebut B
. Proses 1
, 2
, 4
masih membaca blok A
proses 3
sekarang membaca B
.
A
harus membuat salinan baru. Jika Anda bertanya apa yang terjadi jika proses yang sama sekali baru datang dan berubah A
maka penjelasan saya tidak cukup detail untuk itu. Itu akan menjadi implementasi spesifik dan membutuhkan pengetahuan tentang bagaimana Anda ingin sisa implementasi bekerja, seperti penguncian file \ data, dll.
Saya tidak akan mengulangi jawaban yang sama pada Copy-on-Write. Saya pikir jawaban Andrew dan jawaban Charlie sudah membuatnya sangat jelas. Saya akan memberi Anda contoh dari dunia OS, hanya untuk menyebutkan seberapa luas konsep ini digunakan.
Kita dapat menggunakan fork()
atau vfork()
untuk membuat proses baru. vfork mengikuti konsep copy-on-write. Misalnya, proses anak yang dibuat oleh vfork akan berbagi data dan segmen kode dengan proses induk. Ini mempercepat waktu forking. Diharapkan untuk menggunakan vfork jika Anda melakukan exec diikuti oleh vfork. Jadi vfork akan membuat proses anak yang akan berbagi data dan segmen kode dengan induknya tetapi ketika kita memanggil exec, itu akan memuat gambar yang dapat dieksekusi baru di ruang alamat proses anak.
vfork
TIDAK menggunakan SAP. Bahkan jika anak itu menulis sesuatu, itu bisa mengakibatkan perilaku yang tidak jelas dan tidak menyalin halaman !! Bahkan, bisa dibilang sebaliknya. SAP bertindak seperti vfork
sampai ada sesuatu yang dimodifikasi di ruang bersama!
Sebagai contoh lain, Mercurial menggunakan copy-on-write untuk membuat kloning repositori lokal benar-benar "murah".
Prinsipnya sama dengan contoh lainnya, kecuali Anda berbicara tentang file fisik, bukan objek dalam memori. Awalnya, klon bukan duplikat tetapi tautan keras ke aslinya. Saat Anda mengubah file di klon, salinan ditulis untuk mewakili versi baru.
Saya menemukan ini artikel bagus tentang zval di PHP, yang disebutkan SAPI juga:
Copy On Write (disingkat 'COW') adalah trik yang dirancang untuk menghemat memori. Ini digunakan lebih umum dalam rekayasa perangkat lunak. Ini berarti bahwa PHP akan menyalin memori (atau mengalokasikan wilayah memori baru) ketika Anda menulis ke simbol, jika yang ini sudah menunjuk ke zval.
Contoh yang baik adalah Git, yang menggunakan strategi untuk menyimpan gumpalan. Mengapa menggunakan hash? Sebagian karena ini lebih mudah untuk melakukan perbedaan, tetapi juga karena membuatnya lebih mudah untuk mengoptimalkan strategi KK. Ketika Anda membuat komit baru dengan beberapa file perubahan, sebagian besar objek dan pohon tidak akan berubah. Oleh karena itu komit, akan melalui berbagai petunjuk yang terbuat dari referensi hash banyak objek yang sudah ada, membuat ruang penyimpanan yang diperlukan untuk menyimpan seluruh sejarah jauh lebih kecil.
Selanjutnya adalah implementasi Python copy-on-write (COW) menggunakan pola desain dekorator . Referensi ke Value
objek abadi dipegang oleh CowValue
objek yang bisa berubah (dekorator). The CowValue
objek depan semua membaca permintaan ke berubah Value
objek dan penyadapan semua permintaan menulis dengan menciptakan berubah baru Value
objek dengan negara yang benar. The CowValue
objek harus dangkal disalin antara variabel untuk memungkinkan berbagi dari Value
objek.
import abc
import copy
class BaseValue(abc.ABC):
@abc.abstractmethod
def read(self):
raise NotImplementedError
@abc.abstractmethod
def write(self, data):
raise NotImplementedError
class Value(BaseValue):
def __init__(self, data):
self.data = data
def read(self):
return self.data
def write(self, data):
pass
class CowValue(BaseValue):
def __init__(self, data):
self.value = Value(data)
def read(self):
return self.value.read()
def write(self, data):
self.value = Value(data)
v = CowValue(1)
w = copy.copy(v) # shares the immutable Value object
assert v.read() == w.read()
assert id(v.value) == id(w.value)
w.write(2) # creates a new immutable Value object with the correct state
assert v.read() != w.read()
assert id(v.value) != id(w.value)