porque o comando linux cp não consome disco IO?

6

os: centos7

arquivo de teste: a.txt 1.2G

comando monitor: iostat -xdm 1

The first scene:
cp a.txt b.txt        #b.txt is not exist

Thesecondscene:cpa.txtb.txt#b.txtisexist

Por que a primeira cena não consome IO, mas a segunda cena consome IO?

    
por tairyao 14.05.2017 / 10:34

1 resposta

7

Pode ser que os dados não tenham sido liberados para o disco durante a primeira operação cp , mas durante o segundo.

Tente definir vm.dirty_background_bytes como algo pequeno, como 1048576 (1 MiB) para ver se esse é o caso; execute sysctl -w vm.dirty_background_bytes=1048576 e, em seguida, seu primeiro cenário cp mostre E / S.

O que está acontecendo aqui?

Exceto em casos de E / S síncrona e / ou direta, as gravações no disco ficam armazenadas em buffer na memória até que um limite seja atingido e, nesse ponto, elas começam a ser liberadas para o disco em segundo plano. Esse limite não tem um nome oficial, mas é controlado por vm.dirty_background_bytes e vm.dirty_background_ratio , então eu o chamarei de "Limite de fundo sujo". A partir dos documentos do kernel :

vm.dirty_background_bytes

Contains the amount of dirty memory at which the background kernel flusher threads will start writeback.

Note: dirty_background_bytes is the counterpart of dirty_background_ratio. Only one of them may be specified at a time. When one sysctl is written it is immediately taken into account to evaluate the dirty memory limits and the other appears as 0 when read.

dirty_background_ratio

Contains, as a percentage of total available memory that contains free pages and reclaimable pages, the number of pages at which the background kernel flusher threads will start writing out dirty data.

The total available memory is not equal to total system memory.

vm.dirty_bytes e vm.dirty_ratio

Há um segundo limite, além deste. Bem, mais um limite do que um limite, e é controlado por vm.dirty_bytes e vm.dirty_ratio . Novamente, ele não tem um nome oficial, então vamos chamá-lo de "Dirty Limit". Uma vez que dados suficientes tenham sido "gravados", mas não comprometidos com o dispositivo de bloco subjacente, outras tentativas de write terão que esperar pela conclusão da E / S de gravação. (Os detalhes precisos de quais dados eles terão que esperar não são claros para mim e podem ser uma função do agendador de E / S. Não sei.)

Por quê?

Os discos são lentos. Além disso, enquanto o cabeçote de R / W em um disco está se movendo para atender a uma solicitação de leitura, nenhuma solicitação de gravação pode ser atendida até que a solicitação de leitura seja concluída e a solicitação de gravação possa ser iniciada. (E vice-versa)

Eficiência

É por isso que armazenamos em buffer solicitações de gravação em dados de memória e cache que lemos; nós movemos o trabalho do disco lento para a memória mais rápida. Quando, por fim, enviamos os dados para o disco, temos uma boa quantidade de dados para trabalhar e podemos tentar escrevê-los de maneira a minimizar o tempo de busca. (Se você estiver usando um SSD, substitua o conceito de tempo de busca por disco com o reflash de blocos SSD; o reflash consome a vida útil do SSD e é uma operação lenta, que os SSDs tentam - com vários graus de sucesso - ocultar com suas próprias gravações cache.)

Podemos sintonizar quantos dados ficam armazenados em buffer antes que o kernel tente gravá-los no disco usando vm.dirty_background_bytes e vm.dirty_background_ratio .

Demasiado gravar dados em buffer!

Se a quantidade de dados que você está escrevendo for muito grande para a rapidez com que está atingindo o disco, você acabará consumindo toda a memória do sistema. Primeiro, seu cache de leitura desaparecerá, significando que menos solicitações de leitura serão atendidas da memória e terão que ser atendidas a partir do disco, retardando ainda mais suas gravações! Se sua pressão de escrita ainda não diminuir, eventualmente, as alocações de memória terão que esperar que o cache de gravação seja liberado, o que será ainda mais perturbador.

Portanto, temos vm.dirty_bytes (e vm.dirty_ratio ); ele nos permite dizer: "ei, espere um minuto, é realmente hora de termos os dados no disco, antes que isso piore".

Ainda muitos dados

No entanto, colocar uma parada na E / S é muito perturbador; o disco já está lento na perspectiva dos processos de leitura, e pode levar vários segundos para vários minutos para que os dados sejam liberados; considere vm.dirty_bytes padrão de 20. Se você tiver um sistema com 16GiB de RAM e nenhuma troca, você poderá encontrar sua E / S bloqueada enquanto espera que 3.4GiB de dados sejam liberados para o disco. Em um servidor com 128GiB de RAM? Você vai ter um tempo de espera de serviços enquanto espera em 27.5GiB de dados!

Portanto, é útil manter o vm.dirty_bytes (ou vm.dirty_ratio , se você preferir) bastante baixo, de modo que, se você atingir esse limite rígido, será apenas minimamente prejudicial para os seus serviços.

Quais são os valores bons?

Com esses ajustes, você está sempre negociando entre taxa de transferência e latência. Buffer muito, e você terá uma grande taxa de transferência, mas uma latência terrível. Buffer muito pouco, e você terá um throughput terrível, mas grande latência.

Em estações de trabalho e laptops com discos únicos, gosto de definir vm.dirty_background_bytes para cerca de 1 MiB e vm.dirty_bytes para entre 8 MiB e 16 MiB. É muito raro encontrar um benefício de throughput além de 16 MiB para sistemas de usuário único, mas as restrições de latência podem ficar muito ruins para cargas de trabalho síncronas, como armazenamentos de dados de navegadores da Web.

Em qualquer coisa com uma matriz de paridade distribuída, eu acho que alguns múltiplos da largura da faixa da matriz são um bom valor inicial para vm.dirty_background_bytes ; reduz a probabilidade de precisar executar uma sequência de leitura / atualização / gravação enquanto atualiza a paridade, melhorando o rendimento da matriz.

Para vm.dirty_bytes , depende da latência que seus serviços podem sofrer. Eu, pessoalmente, gosto de calcular o rendimento teórico do dispositivo de bloco, usá-lo para calcular a quantidade de dados que ele poderia mover em 100 ms ou mais e definir vm.dirty_bytes de acordo. Um atraso de 100 ms é enorme, mas não é catastrófico (no meu ambiente).

Tudo isso depende do seu ambiente; estes são apenas um ponto de partida para descobrir o que funciona bem para você.

    
por 14.05.2017 / 21:22