Apa itu copy-on-write?

133

Saya ingin tahu apa itu copy-on-write dan digunakan untuk apa? Istilah 'copy-on-write array' disebutkan beberapa kali dalam tutorial Sun JDK tapi saya tidak mengerti apa artinya.

hhafez
sumber

Jawaban:

155

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.

Andrew Hare
sumber
apapun array biasa digunakan untuk ... Namun, dalam beberapa situasi, jenis strategi ini menghasilkan hasil yang lebih optimal.
Andrew Flanagan
3
@hhafez: Linux menggunakannya saat digunakan clone()untuk mengimplementasikan fork()- memori proses induk adalah COWed untuk anak.
Kerrek SB
@hhafez Beberapa sistem file menggunakan CoW , misalnya, BTRFS .
Geremia
Apakah ini cara kerja SandboxIE? ketika program sandboxed ingin menimpa sesuatu sandboxie mencegat operasi sistem file dan menyalin file ke folder sandbox dan memungkinkan program menulis ke file sandbox bukan asli. Apakah itu disebut Salin saat menulis?
Ronnie Matthews
Bagaimana penggabungan terjadi pada akhirnya? Jika ada N salinan, yang mana yang disimpan pada akhirnya untuk menghemat disk katakan?
SimpleGuy
59

"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.

Charlie Martin
sumber
1
Jika Anda melakukan perubahan, bagaimana orang lain mendapat pemberitahuan tentang salinan baru Anda? Bukankah mereka akan melihat data yang salah.
powder366
12
@ powder366 - Tidak, mereka tidak akan melihat data yang salah karena ketika Anda membuat perubahan saat itulah salinan dibuat. Misalnya Anda memiliki blok data yang disebut A. Proses 1, 2, 3, 4masing-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 3ingin membuat perubahan pada salinannya A, proses 3sekarang akan benar-benar membuat salinan Adan membuat blok data baru yang disebut B. Proses 1, 2, 4masih membaca blok Aproses 3sekarang membaca B.
Puddler
1
@Puddler apa yang akan terjadi jika perubahan dilakukan dalam 'A'. Semua proses akan membaca informasi yang diperbarui atau yang lama?
Pengembang
3
@ Pengembang: Ya proses mana pun yang membuat perubahan Aharus membuat salinan baru. Jika Anda bertanya apa yang terjadi jika proses yang sama sekali baru datang dan berubah Amaka 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.
Puddler
10

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.

Shamik
sumber
3
"vfork mengikuti konsep copy-on-write". Silakan pertimbangkan untuk mengubah baris ini. vforkTIDAK 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 vforksampai ada sesuatu yang dimodifikasi di ruang bersama!
Pavan Manjunath
Sepenuhnya setuju dengan Pavan. Hapus baris "vfork mengikuti konsep copy-on-write". Sekarang suatu hari, SAP digunakan dalam garpu sebagai optimisasi, sehingga berfungsi seperti vfork dan tidak membuat salinan data orang tua untuk proses anak (jika kita hanya memanggil exec * pada anak)
Shekhar Kumar
7

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.

harpo
sumber
2

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.

Amir Shabani
sumber
0

Ini juga digunakan dalam Ruby 'Enterprise Edition' sebagai cara yang rapi untuk menghemat memori.

Chris
sumber
2
Saya tidak berpikir maksudnya "digunakan untuk" dalam arti itu.
spydon
0

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.

Sam Keays
sumber
0

Ini adalah konsep perlindungan memori. Dalam kompiler ini membuat salinan tambahan untuk memodifikasi data pada anak dan data yang diperbarui ini tidak mencerminkan data orang tua.

Sushant
sumber
0

Selanjutnya adalah implementasi Python copy-on-write (COW) menggunakan pola desain dekorator . Referensi ke Valueobjek abadi dipegang oleh CowValueobjek yang bisa berubah (dekorator). The CowValueobjek depan semua membaca permintaan ke berubah Valueobjek dan penyadapan semua permintaan menulis dengan menciptakan berubah baru Valueobjek dengan negara yang benar. The CowValueobjek harus dangkal disalin antara variabel untuk memungkinkan berbagi dari Valueobjek.

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)
Maggyero
sumber