Che cos'è il copy-on-write?


133

Vorrei sapere cos'è il copy-on-write e a cosa serve? Il termine "array copy-on-write" è menzionato più volte nei tutorial di Sun JDK ma non ho capito cosa significasse.

Risposte:


155

Stavo per scrivere la mia spiegazione, ma questo articolo di Wikipedia lo riassume praticamente.

Ecco il concetto di base:

Copy-on-write (a volte indicato come "COW") è una strategia di ottimizzazione utilizzata nella programmazione informatica. L'idea fondamentale è che se più chiamanti chiedono risorse che inizialmente sono indistinguibili, è possibile fornire loro puntatori alla stessa risorsa. Questa funzione può essere mantenuta fino a quando un chiamante non tenta di modificare la sua "copia" della risorsa, a quel punto viene creata una vera copia privata per impedire che le modifiche diventino visibili a tutti gli altri. Tutto ciò accade in modo trasparente ai chiamanti. Il vantaggio principale è che se un chiamante non apporta mai alcuna modifica, non è mai necessario creare una copia privata.

Anche qui è un'applicazione di un uso comune di COW:

Il concetto di COW viene utilizzato anche per la manutenzione di istantanee istantanee su server di database come Microsoft SQL Server 2005. Le istantanee istantanee preservano una vista statica di un database memorizzando una copia di pre-modifica dei dati durante l'aggiornamento dei dati di base. Le istantanee sono utilizzate per test di utilizzo o report dipendenti dal momento e non devono essere utilizzate per sostituire i backup.


qualsiasi cosa venga utilizzata per un array normale ... tuttavia, in alcune situazioni, questo tipo di strategia porta a risultati più ottimizzati.
Andrew Flanagan,

3
@hhafez: Linux lo usa quando lo usa clone()per implementare fork()- la memoria del processo genitore è COWed per il bambino.
Kerrek SB,

@hhafez Alcuni file system usano mucca, per esempio, BTRFS .
Geremia,

È così che funziona SandboxIE? quando un programma sandbox vuole sovrascrivere qualcosa sandboxie intercetta il funzionamento del file system e copia il file nella cartella sandbox e consente al programma di scrivere nel file sandbox anziché nell'originale. Si chiama Copy on write?
Ronnie Matthews,

Come avviene l'unione alla fine? Se ci sono N copie, quale verrà conservata alla fine per salvare sul disco?
SimpleGuy

59

"Copia su scrittura" significa più o meno quello che sembra: ognuno ha una singola copia condivisa degli stessi dati fino a quando non viene scritta , e quindi viene fatta una copia. Di solito, la copia su scrittura viene utilizzata per risolvere i problemi di concorrenza. In ZFS , ad esempio, i blocchi di dati su disco sono allocati copia su scrittura; fintanto che non ci sono modifiche, si mantengono i blocchi originali; una modifica ha modificato solo i blocchi interessati. Ciò significa che viene assegnato il numero minimo di nuovi blocchi.

Questi cambiamenti sono anche generalmente implementati essere transazionale , cioè, hanno le ACID proprietà. Questo elimina alcuni problemi di concorrenza, perché in questo caso sei sicuro che tutti gli aggiornamenti sono atomici.


1
Se fai una modifica, come viene avvisato l'altro della tua nuova copia? Non vedrebbero i dati sbagliati.
powder366,

12
@ powder366 - No, non vedrebbero i dati sbagliati perché quando si effettua una modifica, in realtà viene eseguita una copia. Ad esempio hai un blocco di dati chiamato A. Processo 1, 2, 3, 4ogni voglia di fare una copia di esso e iniziare a leggerlo, in una "copy on write" sistema di nulla viene copiato eppure tutto è ancora leggendo A. Ora il processo 3vuole apportare una modifica alla sua copia A, 3ora il processo effettivamente eseguirà una copia Ae creerà un nuovo blocco di dati chiamato B. Processo 1, 2, 4stanno ancora leggendo blocco Aprocesso 3è ora di lettura B.
Puddler,

1
@Puddler cosa accadrà se vengono apportate modifiche in 'A'. Tutti i processi leggeranno le informazioni aggiornate o vecchie?
Sviluppatore

3
@Developer: Beh, qualunque processo stia effettuando una modifica Adovrebbe creare una nuova copia. Se stai chiedendo cosa succede se un processo completamente nuovo si presenta e cambia, Aallora la mia spiegazione non è abbastanza dettagliata. Sarebbe specifico per l'implementazione e richiederebbe la conoscenza di come vuoi che funzioni il resto dell'implementazione, come file \ data
block

10

Non ripeterò la stessa risposta su Copia su scrittura. Penso che la risposta di Andrew e quella di Charlie abbiano già reso molto chiaro. Vi farò un esempio dal mondo dei sistemi operativi, solo per menzionare quanto ampiamente viene usato questo concetto.

Possiamo usare fork()o vfork()per creare un nuovo processo. vfork segue il concetto di copia su scrittura. Ad esempio, il processo figlio creato da vfork condividerà i dati e il segmento di codice con il processo padre. Questo accelera il tempo di forking. Si prevede di utilizzare vfork se si esegue exec seguito da vfork. Quindi vfork creerà il processo figlio che condividerà i dati e il segmento di codice con il suo genitore ma quando chiamiamo exec, caricherà l'immagine di un nuovo eseguibile nello spazio degli indirizzi del processo figlio.


3
"vfork segue il concetto di copia su scrittura". Ti preghiamo di considerare di cambiare questa linea. vforkNON usa MUCCA. Infatti se il bambino scrive qualcosa, può comportare un comportamento indefinito e non copiare le pagine !! In effetti, puoi dire che è vero il contrario. COW si comporta come vforkfino a quando qualcosa non viene modificato nello spazio condiviso!
Pavan Manjunath,

Completamente d'accordo con Pavan. Rimuovi le righe "vfork segue il concetto di copia su scrittura". Ora un giorno, COW viene utilizzato nel fork come ottimizzazione, in modo che agisca come vfork e non crei una copia dei dati dei genitori per il processo figlio (se chiamiamo solo exec * in figlio)
Shekhar Kumar

7

Giusto per fornire un altro esempio, Mercurial utilizza la funzione di copia su scrittura per rendere la clonazione dei repository locali un'operazione davvero "economica".

Il principio è lo stesso degli altri esempi, tranne per il fatto che stai parlando di file fisici anziché di oggetti in memoria. Inizialmente, un clone non è un duplicato ma un collegamento reale all'originale. Quando si modificano i file nel clone, le copie vengono scritte per rappresentare la nuova versione.


2

Ho trovato questo buon articolo su zval in PHP, che menzionava anche COW:

Copy On Write (abbreviato in 'COW') è un trucco progettato per risparmiare memoria. È usato più in generale nell'ingegneria del software. Significa che PHP copierà la memoria (o allocherà una nuova area di memoria) quando si scrive su un simbolo, se questo puntava già a uno zval.


0

Viene anche usato in Ruby "Enterprise Edition" come un modo pulito per risparmiare memoria.


2
Non penso che intendesse "usato per" in quel senso.
spydon,

0

Un buon esempio è Git, che utilizza una strategia per archiviare i BLOB. Perché usa gli hash? In parte perché questi sono più facili da eseguire su differenze, ma anche perché semplifica l'ottimizzazione di una strategia COW. Quando si effettua un nuovo commit con poche modifiche ai file, la stragrande maggioranza degli oggetti e degli alberi non cambierà. Pertanto il commit, attraverso vari puntatori fatti di hash, farà riferimento a un gruppo di oggetti già esistenti, rendendo lo spazio di archiviazione richiesto per memorizzare l'intera storia molto più piccola.


0

È un concetto di protezione della memoria. In questo compilatore crea una copia aggiuntiva per modificare i dati nel figlio e questi dati aggiornati non si riflettono nei dati dei genitori.


0

Qui di seguito è una implementazione Python copia-su-scrittura (COW) utilizzando il modello di progettazione del decoratore . Un riferimento a un Valueoggetto immutabile è trattenuto da un CowValueoggetto mutabile (il decoratore). L' CowValueoggetto inoltra tutte le richieste di lettura Valueall'oggetto immutabile e intercetta tutte le richieste di scrittura creando un nuovo Valueoggetto immutabile con lo stato corretto. L' CowValueoggetto deve essere copiato in modo superficiale tra le variabili per consentire la condivisione Valuedell'oggetto.

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.