O que é copiar na gravação?

133

Gostaria de saber o que é copiar em gravação e para que é usado? O termo 'matriz de copiar na gravação' é mencionado várias vezes nos tutoriais do Sun JDK, mas eu não entendi o que isso significava.

hhafez
fonte

Respostas:

155

Eu ia escrever minha própria explicação, mas este artigo da Wikipedia resume bastante.

Aqui está o conceito básico:

A cópia na gravação (às vezes chamada de "COW") é uma estratégia de otimização usada na programação de computadores. A idéia fundamental é que, se vários chamadores solicitarem recursos inicialmente indistinguíveis, você poderá fornecer indicadores para o mesmo recurso. Essa função pode ser mantida até que um chamador tente modificar sua "cópia" do recurso, quando uma cópia privada verdadeira é criada para impedir que as alterações fiquem visíveis para todos os outros. Tudo isso acontece de forma transparente para os chamadores. A principal vantagem é que, se um chamador nunca fizer nenhuma modificação, nenhuma cópia privada será criada.

Também aqui está uma aplicação de um uso comum do COW:

O conceito COW também é usado na manutenção de instantâneos instantâneos em servidores de banco de dados como o Microsoft SQL Server 2005. Os instantâneos instantâneos preservam uma visão estática de um banco de dados, armazenando uma cópia de pré-modificação dos dados quando os dados subjacentes são atualizados. Instantâneos instantâneos são usados ​​para testes de uso ou relatórios dependentes de momento e não devem ser usados ​​para substituir backups.

Andrew Hare
fonte
qualquer coisa que uma matriz regular seja usada ... no entanto, em algumas situações, esse tipo de estratégia resulta em resultados mais otimizados.
Andrew Flanagan
3
@hafez: o Linux usa quando clone()implementa fork()- a memória do processo pai é COW para a criança.
precisa saber é o seguinte
@hhafez Alguns sistemas de arquivos usam CoW, por exemplo, BTRFS .
Geremia
É assim que o SandboxIE funciona? quando um programa em área restrita deseja substituir algo, o sandbox intercepta a operação do sistema de arquivos e copia o arquivo para a pasta área restrita e permite que o programa grave no arquivo protegido em vez do original. Isso se chama Copiar na gravação?
Ronnie Matthews
Como a fusão acontece eventualmente? Se houver N cópias, qual delas será mantida para salvar no disco, digamos?
SimpleGuy
59

"Copiar na gravação" significa mais ou menos o que parece: todos têm uma única cópia compartilhada dos mesmos dados até que sejam gravados e, em seguida, uma cópia é feita. Geralmente, a cópia na gravação é usada para resolver os tipos de problemas de simultaneidade. No ZFS , por exemplo, os blocos de dados no disco são alocados na cópia; contanto que não haja alterações, você mantém os blocos originais; uma mudança alterou apenas os blocos afetados. Isso significa que o número mínimo de novos blocos é alocado.

Essas alterações também são geralmente implementadas para serem transacionais , ou seja, elas têm as propriedades ACID . Isso elimina alguns problemas de simultaneidade, porque você garante que todas as atualizações são atômicas.

Charlie Martin
fonte
1
Se você fizer uma alteração, como o outro é notificado da sua nova cópia? Eles não veriam os dados errados.
powder366
12
@ powder366 - Não, eles não veriam os dados errados porque quando você faz uma alteração é quando uma cópia é realmente feita. Por exemplo, você tem um bloco de dados chamado A. Processo 1, 2, 3, 4cada um quer fazer uma cópia do mesmo e começar a lê-lo, em uma "cópia na escrita" Sistema nada é copiado mas tudo ainda está lendo A. Agora, o processo 3deseja alterar sua cópia A, 3agora o processo efetua uma cópia Ae cria um novo bloco de dados chamado B. Processo 1, 2, 4ainda está lendo bloco Aprocesso 3está agora lendo B.
Puddler
1
@Puddler o que acontecerá se forem feitas alterações em 'A'. Todos os processos estarão lendo as informações atualizadas ou antigas?
Desenvolvedor
3
@ Desenvolvedor: Bem, qualquer processo que esteja fazendo uma alteração Adeve estar criando uma nova cópia. Se você está perguntando o que acontece se um processo totalmente novo surgir e mudar A, minha explicação não entra em detalhes suficientes para isso. Isso seria implementação específica e exigem conhecimento sobre como você deseja que o resto da aplicação ao trabalho, tais como arquivo \ bloqueio de dados, etc.
Puddler
10

Não repetirei a mesma resposta em Copy-on-Write. Acho que a resposta de Andrew e a de Charlie já deixaram muito claro. Vou dar um exemplo do mundo do SO, apenas para mencionar o quão amplamente esse conceito é usado.

Podemos usar fork()ou vfork()criar um novo processo. O vfork segue o conceito de cópia na gravação. Por exemplo, o processo filho criado pelo vfork compartilhará o segmento de dados e código com o processo pai. Isso acelera o tempo de bifurcação. Espera-se usar o vfork se você estiver executando exec seguido pelo vfork. Portanto, o vfork criará o processo filho que compartilhará os dados e o segmento de código com seu pai, mas quando chamamos exec, ele carregará a imagem de um novo executável no espaço de endereço do processo filho.

Shamik
fonte
3
"o vfork segue o conceito de cópia na gravação". Por favor, considere alterar esta linha. vforkNÃO usa VACA. De fato, se a criança escreve algo, pode resultar em comportamento indefinido e não copiar páginas! De fato, você pode dizer que o contrário é verdade. COW age como vforkaté que algo seja modificado no espaço compartilhado!
Pavan Manjunath
Concordo totalmente com Pavan. Remova as linhas "vfork segue o conceito de cópia na gravação". Agora, um dia, COW é usado no garfo como uma otimização, de modo que ele age como vfork e não fazer uma cópia dos dados do pai para o processo de criança (se apenas chamadas * exec em criança)
Shekhar Kumar
7

Apenas para dar outro exemplo, o Mercurial usa a cópia na gravação para tornar a clonagem de repositórios locais uma operação realmente "barata".

O princípio é o mesmo dos outros exemplos, exceto que você está falando sobre arquivos físicos em vez de objetos na memória. Inicialmente, um clone não é uma duplicata, mas um vínculo físico com o original. Conforme você altera os arquivos no clone, as cópias são gravadas para representar a nova versão.

harpo
fonte
2

Encontrei este bom artigo sobre o zval no PHP, que também mencionou o COW:

Copy On Write (abreviado como 'COW') é um truque projetado para economizar memória. É usado de maneira mais geral na engenharia de software. Isso significa que o PHP copiará a memória (ou alocará nova região de memória) quando você escrever em um símbolo, se este já estiver apontando para um zval.

Amir Shabani
fonte
0

Também é usado no Ruby 'Enterprise Edition' como uma maneira elegante de economizar memória.

Chris
fonte
2
Eu não acho que ele quis dizer "usado para" nesse sentido.
Spydon # 5/15
0

Um bom exemplo é o Git, que usa uma estratégia para armazenar blobs. Por que ele usa hashes? Em parte porque essas são mais fáceis de executar, mas também porque simplifica a otimização de uma estratégia de COW. Quando você faz um novo commit com poucos arquivos, a grande maioria dos objetos e as árvores não são alteradas. Portanto, o commit, através de vários ponteiros feitos de hashes, fará referência a um monte de objetos que já existem, tornando o espaço de armazenamento necessário para armazenar todo o histórico muito menor.

Sam Keays
fonte
0

É um conceito de proteção de memória. Neste compilador, cria uma cópia extra para modificar os dados no filho e esses dados atualizados não refletem nos dados dos pais.

Sushant
fonte
0

A seguir, é apresentada uma implementação Python de copiar-em-gravar (COW), usando o padrão de design do decorador . Uma referência a um Valueobjeto imutável é mantida por um CowValueobjeto mutável (o decorador). O CowValueobjeto encaminha todas as solicitações de leitura para o Valueobjeto imutável e intercepta todas as solicitações de gravação criando um novo Valueobjeto imutável com o estado correto. O CowValueobjeto deve ser copiado superficialmente entre as variáveis ​​para permitir o compartilhamento do Valueobjeto.

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
fonte