Estou lendo a Interface de programação do Linux .
49.9 MAP_NORESERVE e superalocação de espaço de swap
Alguns aplicativos criam mapeamentos grandes (geralmente anônimos privados), mas usam apenas uma pequena parte da região mapeada. Por exemplo, certos tipos de aplicativos científicos alocam um array muito grande, mas operam em apenas alguns elementos amplamente separados do array (um chamado array esparso).
Se o kernel sempre alocasse (ou reservasse) espaço de troca suficiente para todos esses mapeamentos, muito espaço de troca seria potencialmente desperdiçado. Em vez disso, o kernel pode reservar espaço de troca para as páginas de um mapeamento apenas quando elas forem realmente necessárias (ou seja, quando o aplicativo acessar uma página). Essa abordagem é chamada de reserva de troca lenta e tem a vantagem de que a memória virtual total usada pelos aplicativos pode exceder o tamanho total da RAM mais o espaço de troca.
Para colocar as coisas de outra forma, a reserva de troca lenta permite que o espaço de troca seja supercomprometido. Isso funciona bem, desde que todos os processos não tentem acessar todo o intervalo de seus mapeamentos. ...
Tanto quanto sei, o espaço de troca é um pedaço de espaço em disco, reservado para troca de memória. Quando essas páginas na memória estão inativas, elas são trocadas no espaço de troca no disco. É como um cache de segundo nível para memória/ram.
Então, o que diabos é esse mecanismo de reserva de swap preguiçoso ?
Deixe-me demonstrar minha confusão com um exemplo.
Alguns aplicativos criam mapeamentos grandes (geralmente anônimos privados)....
Ok, então suponha que eu tenha malloc
um grande array de 16384(4096*4)
bytes (crie mapeamentos grandes (geralmente anônimos privados)) e opere apenas alguns elementos amplamente separados do array.
Então algumas páginas inativas são trocadas em espaço de troca, certo? Digamos que 0-4095(4096B)
, 8192-12287(4096B)
estejam na memória e todas as outras páginas inativas, 4096-8191(4096B)
, 12288-16383(4096B)
sejam trocadas no espaço de troca.
Então o que significa dizer:
Em vez disso, o kernel pode reservar espaço de troca para as páginas de um mapeamento apenas quando elas forem realmente necessárias (ou seja, quando o aplicativo acessar uma página).
Onde mais essas páginas inativas ( 4096-8191(4096B)
e 12288-16383(4096B)
) podem ficar, se não ficarem no espaço de troca ? O texto parece indicar que existe um cache de 3º nível para o espaço de troca.
memory -> swap space (disk) -> ????
Swap não é realmente um cache de segundo nível para memória; é um dos vários armazenamentos de apoio para memória . Quando o kernel precisa alocar uma página de memória física, mas não tem memória livre suficiente, ele precisa despejar outra página; ele só pode fazer isso se o conteúdo da página removida for descartável ou puder ser restaurado de outro lugar. Isso em algum outro lugar está fazendo backup: pode ser um arquivo no disco ( por exemplo , para executáveis ou arquivos mapeados) ou alguma área de troca.
A reserva de swap entra em ação quando a contabilização da memória acompanha o overcommitting (consulte a tabela 49-4 em LPI ). Quando overcommitting não é permitido, o kernel precisa determinar, no momento da alocação, se uma alocação é possível. Para mapeamentos graváveis privados e mapeamentos anônimos compartilhados, isso significa que ele deve ter espaço de endereço suficiente e espaço suficiente na troca (para que o kernel possa garantir que o conteúdo da memória mapeada possa ser escrito lá, garantindo assim que as gravações no memória mapeada nunca causará
SIGSEGV
).A reserva de swap preguiçosa é necessária para overcommit: significa que o kernel pode alocar um mapa de memória baseado em swap sem reservar o espaço de swap correspondente. Conforme mencionado no LPI , isso permite que os programas aloquem muito mais memória do que está realmente disponível e deve ser solicitado usando
MAP_NORESERVE
. A reserva só acontece quando uma página é gravada, o que significa que as gravações podem falharSIGSEGV
ou resultar na intervenção do assassino OOM.Isso se torna significativo para alocações muito maiores do que seu exemplo de 16 KiB. Imagine que você queira um array esparso de 64GiB, 262.144×262.144, para tornar seu programa mais fácil de escrever: com reserva estrita, você precisaria ter toda essa memória disponível; sem reservas estritas, você não, e apenas as páginas para as quais você escreve serão realmente alocadas.
Observe que tudo isso é específico do Linux e fortemente vinculado à política de overcommit do sistema escolhido (
/proc/sys/vm/overcommit_memory
): nos modos 1 (sempre overcommit) e 2 (nunca overcommit),MAP_NORESERVE
não muda nada, só tem efeito no modo 0.Um pedaço de que tipo de espaço? Memória virtual.
É fácil para o kernel dar a cada processo a quantidade de memória virtual que desejar. Essa é a parte preguiçosa e exagerada. O exemplo da matriz científica esparsa quer mostrar que muitas vezes é uma boa ideia ser preguiçoso. O array inteiro não será usado de uma vez, então outros programas podem ser executados ao mesmo tempo.
Mas não é realmente mais rápido que "o" disco, na maioria das vezes (sem um dispositivo de troca dedicado)
É o contrário, especialmente com overcommitting:
A troca transforma a RAM (física) em um cache para o(s) dispositivo(s) de armazenamento.
(ou seja, RAM não é algo para se ter e manter para um processo, mas é a área de trabalho para as páginas ativas de cada processo, incluindo arquivos mapeados).
Aqui trata-se de sobrecarregar também o espaço de troca, não apenas a RAM. Com ou sem swap, pode levar a uma situação de OOM após o overcommiting.