Linux Virtual Memory Management e lentidão ao copiar arquivos grandes para mídia lenta
Se você usa Linux 64 bits e tem bastante memória RAM, alguma vez já notou uma lentidão extrema - a ponto de algumas vezes deixar o sistema irresponsivo - ao copiar arquivos grandes para mídias lentas, como pendrives USB? Até o Linus Torvalds já abordou esse problema, mesmo assim, ainda não há uma solução definitiva, mas existem tunings do subsistema de Virtual Memory do kernel do Linux que minimizam esse problema.
Introdução
Se você usa Linux, alguma vez já notou uma lentidão extrema - a ponto de algumas vezes deixar o sistema irresponsivo - ao copiar arquivos grandes, de alguns gigabytes, para mídias lentas, como pendrives USB (especialmente aqueles "genéricos", que oferecem baixa performance)? Se o seu computador é 64 bits e tem bastante memória RAM (8 GB ou mais), muito provavelmente já notou isso. Tanto é que até o Linus Torvalds já abordou esse problema [1], há alguns anos atrás; mesmo assim, ainda não há uma solução definitiva, mas existem tunings do subsistema de Virtual Memory do kernel do Linux que minimizam esse problema.
Antes de continuar, é preciso entender um pouco sobre alguns conceitos do gerenciamento de memória do Linux. Não vou entrar em muitos detalhes, pois este não é um artigo acadêmico, mas no final colocarei algumas referências para quem quiser se aprofundar mais.
Um primeiro conceito que deve ficar claro é: o Linux trabalha por padrão com buffered I/O. De forma simplificada, isso significa que as operações de escrita simplesmente copiam os dados para a memória RAM [2], e depois, em background, o kernel vai fazendo a escrita em si (flush) no dispositivo destino. Dado isto, entra o segundo conceito: dirty memory, que é justamente essa informação que está temporariamente na memória RAM, esperando ser escrita em um dispositivo de armazenamento.
Acontece que, quando copiamos muitos dados para uma mídia lenta, há um problema de bufferbloat, em que a fila de I/O requests fica gigantesca. Isso acarreta toda a lentidão, já que outras operações de I/O são também afetadas, além de outros efeitos colaterais.
Dentre as alternativas propostas para minimizar este problema, as mais simples envolvem ajustar os parâmetros relacionados à dirty memory do subsistema de Virtual Memory do kernel [3][4]. O objetivo é deixar a fila menor, definindo um threshold mais agressivo para o flush da dirty memory para o dispositivo (o daemon que controla isso é o "pdflush", para quem quiser se aprofundar).
Antes de continuar, é preciso entender um pouco sobre alguns conceitos do gerenciamento de memória do Linux. Não vou entrar em muitos detalhes, pois este não é um artigo acadêmico, mas no final colocarei algumas referências para quem quiser se aprofundar mais.
Um primeiro conceito que deve ficar claro é: o Linux trabalha por padrão com buffered I/O. De forma simplificada, isso significa que as operações de escrita simplesmente copiam os dados para a memória RAM [2], e depois, em background, o kernel vai fazendo a escrita em si (flush) no dispositivo destino. Dado isto, entra o segundo conceito: dirty memory, que é justamente essa informação que está temporariamente na memória RAM, esperando ser escrita em um dispositivo de armazenamento.
Acontece que, quando copiamos muitos dados para uma mídia lenta, há um problema de bufferbloat, em que a fila de I/O requests fica gigantesca. Isso acarreta toda a lentidão, já que outras operações de I/O são também afetadas, além de outros efeitos colaterais.
Dentre as alternativas propostas para minimizar este problema, as mais simples envolvem ajustar os parâmetros relacionados à dirty memory do subsistema de Virtual Memory do kernel [3][4]. O objetivo é deixar a fila menor, definindo um threshold mais agressivo para o flush da dirty memory para o dispositivo (o daemon que controla isso é o "pdflush", para quem quiser se aprofundar).