Conceitos do sistema operacional diz
Considere uma leitura sequencial de um arquivo em disco usando as chamadas padrão do sistema open(), read() e write() . Cada acesso de arquivo requer uma chamada de sistema e acesso ao disco .
Alternativamente, podemos usar as técnicas de memória virtual discutidas até agora para tratar a E/S de arquivo como acessos de memória de rotina. Essa abordagem, conhecida como mapeamento de memória de um arquivo , permite que uma parte do espaço de endereço virtual seja logicamente associada ao arquivo. Como veremos, isso pode levar a aumentos significativos de desempenho. O mapeamento de memória de um arquivo é realizado mapeando um bloco de disco para uma página (ou páginas) na memória. O acesso inicial ao arquivo ocorre por meio de paginação de demanda comum, resultando em uma falha de paginação. No entanto, uma parte do arquivo do tamanho de uma página é lida do sistema de arquivos em uma página física (alguns sistemas podem optar por ler mais do que um pedaço de memória do tamanho de uma página de cada vez). Leituras e escritas subsequentes no arquivo são tratadas como acessos de memória de rotina. Manipular arquivos através da memória em vez de incorrer na sobrecarga de usar as chamadas de sistema read() e write() simplifica e acelera o acesso e uso de arquivos.
Você poderia analisar o desempenho do arquivo mapeado na memória?
Se eu estiver correto, o arquivo de mapeamento de memória funciona da seguinte maneira. É preciso uma chamada de sistema para criar um mapeamento de memória. Então, quando ele acessa a memória mapeada, ocorrem falhas de página. As falhas de página também têm sobrecarga.
Como o mapeamento de memória de um arquivo aumenta significativamente o desempenho em relação às chamadas de sistema de E/S padrão?
O mapeamento de memória de um arquivo evita diretamente a cópia de buffers que acontecem com
read()
ewrite()
chamadas. Chamaread()
ewrite()
inclui um ponteiro para buffer no espaço de endereço do processo onde os dados são armazenados. O kernel tem que copiar os dados de/para esses locais. O usommap()
mapeia o arquivo para o espaço de endereço do processo, para que o processo possa endereçar o arquivo diretamente e nenhuma cópia seja necessária.Também não há sobrecarga de chamada do sistema ao acessar o arquivo mapeado na memória após a chamada inicial se o arquivo for carregado na memória na inicial
mmap()
. Se uma página do arquivo mapeado não estiver na memória, o acesso gerará uma falha e exigirá que o kernel carregue a página na memória. Ler um bloco grande comread()
pode ser mais rápido do quemmap()
nesses casos, semmap()
geraria um número significativo de falhas para ler o arquivo. (É possível avisar o kernel com antecedênciamadvise()
para que o kernel possa carregar as páginas com antecedência antes do acesso).Para mais detalhes, há uma questão relacionada no Stack Overflow: mmap() vs. blocos de leitura
Primeiro, na maioria das operações de IO, as características do hardware de armazenamento subjacente dominam o desempenho. Uma matriz RAID5 mal configurada de vinte e nove discos SATA SLOW 5400 rpm em um sistema lento e com falta de memória usando RAID S/W com tamanhos de bloco incompatíveis e sistemas de arquivos desalinhados vai lhe dar um desempenho ruim em comparação com um sistema configurado e alinhado corretamente SSD RAID 1+0 em um controlador de alto desempenho, apesar de qualquer ajuste de software que você possa tentar.
Mas a única maneira de
mmap()
ser significativamente mais rápido é se você ler os mesmos dados mais de uma vez e os dados lidos não forem paginados entre as leituras devido à pressão da memória.Etapas do mapa de memória:
Se o processo apenas executar as etapas 2 e 3 uma vez para cada bit de dados lido, ou os dados forem descartados da memória devido à pressão da memória,
mmap()
será mais lento.read()
degraus:O mapeamento de memória só vai superar isso em termos de desempenho por causa dessa cópia extra do cache de página para processar a memória. Mas uma mera cópia de uma página de memória (ou menos) precisa ser feita várias vezes para superar o custo de configurar o mapeamento - provavelmente. Quantas vezes depende do seu sistema. Largura de banda da memória, como todo o seu sistema está sendo usado, tudo. Por exemplo, se o tempo usado pelo gerenciamento de memória do kernel para configurar o mapeamento não tivesse sido usado por nenhum outro processo, o custo de criar o mapeamento realmente não seria muito alto. Por outro lado, se você tiver muito processamento em seu sistema que envolva muita criação/destruição de mapeamento de memória virtual (ou seja, muitos processos de curta duração), o impacto da E/S mapeada na memória pode ser significativo.
Depois, há o
read()
uso de IO direto:As leituras diretas de IO são praticamente impossíveis de superar em termos de desempenho. Mas você precisa realmente ajustar seus padrões de E/S ao seu hardware para maximizar o desempenho.
Observe que um processo pode controlar muito bem se a leitura de dados causa uma falha de página para o buffer que o processo está usando para ler.
Então, o acesso a arquivos mapeados na memória é mais rápido? Talvez seja, talvez não.
Depende do(s) seu(s) padrão(ões) de acesso. Junto com seu hardware e tudo mais em seu(s) caminho(s) de E/S.
Se você estiver transmitindo um arquivo de vídeo de 30 GB em uma máquina com 4 GB de RAM e nunca voltar e reler nenhum dos dados, o mapeamento de memória do arquivo é provavelmente a pior maneira de lê-lo.
Por outro lado, se você tiver uma tabela de pesquisa de 100 MB para alguns dados que você acessa aleatoriamente bilhões e bilhões de vezes em seu processamento e memória suficiente para que o arquivo nunca seja paginado, o mapeamento de memória esmagará todos os outros métodos de acesso.
Uma grande vantagem dos arquivos mapeados na memória
Os arquivos de mapeamento de memória têm uma enorme vantagem sobre outras formas de IO: simplicidade de código. É realmente difícil superar a simplicidade de acessar um arquivo como se estivesse na memória. E na maioria das vezes, a diferença de desempenho entre o mapeamento de memória de um arquivo e a execução de operações de E/S discretas não é tão grande assim.