Eu estava tentando otimizar meu servidor Linux para lidar com 10.000 threads por processo, enquanto ele faz apenas 382 no momento. De acordo com este artigo, a seguinte fórmula é usada para descobrir o total de threads possíveis:
number of threads = total virtual memory / (stack size*1024*1024)
Isso significa que os threads armazenam todos os seus dados na memória virtual. E, até onde eu sei, a memória virtual é o espaço de troca em uma máquina Linux armazenada em disco rígido que RAM ou cache.
Portanto, minha pergunta é: nossos threads usam o disco rígido para armazenar e processar / armazenar seus dados.
Se sim, esse efeito não afeta o desempenho? Podemos melhorar o desempenho colocando-os na RAM ou no cache? Como?
Se não, como exatamente os threads funcionam?
Atualizar:
De acordo com a resposta do inútil , a memória virtual é um sistema que compreende aproximadamente:
- memória física (RAM)
- quaisquer arquivos de troca que você anexou
- suporte de hardware para converter endereços virtuais em físicos e emitir falhas de página quando um endereço virtual não estiver disponível na memória física
- (kernel) suporte de software para: gerenciar as tabelas de pesquisa usadas pelo hardware que lida com essas falhas de página, puxando as páginas da troca sob demanda
Assim, tudo o que está na memória virtual está coletivamente na RAM (Memória Real) e no Disco Rígido (Arquivos de Troca). E, como James explica em sua resposta, a decisão sobre Ram vs HDD é tomada pelo Kernel usando algoritmos como LRU.
fonte
Respostas:
Não, a memória virtual é um sistema que compreende aproximadamente:
Cabe ao kernel garantir que a memória virtual que você deseja seja armazenada em cache na RAM quando desejar - a menos que você esteja gravando sua própria camada de VM no espaço do usuário (como os bancos de dados costumam fazer, iiuc), apenas não se preocupe.
fonte
sar -B
no Linux).Se o encadeamento estiver realmente em execução, a instrução atual e todas as variáveis que o encadeamento estiver usando deverão estar na memória física.
A maioria (de fato quase todos) dos programas reside na memória virtual e, a maioria dos programas usa memória virtual para armazenamento de variáveis.
Endereços virtuais organizados em blocos chamados páginas (geralmente são blocos de 4096 ou 8192 bytes).
A qualquer momento, cada bloco de memória virtual é armazenado em algum lugar na memória real ou no disco no "espaço de troca" reservado para isso.
O código do seu programa lida com endereços virtuais, quando você ramifica para um endereço virtual ou solicita acesso ao armazenamento em um endereço virtual em que o sistema (geralmente no nível do hardware) localiza o local atual da solicitação de endereço e o mapeia para seu endereço virtual, se o endereço atualmente residir no disco, ele o pagina na memória real e mapeia o endereço.
Obviamente, quando toda a memória física estiver em uso, se alguma coisa for paginada, outra coisa deverá ser paginada, para que o sistema procure a página "Menos Utilizadas Recentemente" e a copie para o disco antes de copiar a página solicitada.
Nos sistemas modernos, existem várias otimizações e truques associados ao armazenamento virtual.
fonte
Primeiro de tudo, você precisa ler mais sobre a memória do computador , porque parece não ter conhecimento nesse campo.
Um encadeamento de execução é a menor unidade de processamento que pode ser agendada por um sistema operacional. A implementação de threads e processos difere de um sistema operacional para outro, mas na maioria dos casos, um thread está contido dentro de um processo. Vários encadeamentos podem existir no mesmo processo e compartilhar recursos como memória, enquanto processos diferentes não compartilham esses recursos.
Portanto, os threads usarão a memória disponível - qualquer que seja o tipo disponível. A quantidade de threads que você pode iniciar depende do tamanho da memória e da quantidade de memória necessária por thread. Se o thread usar heap (não apenas a pilha), ele precisará de mais memória e, nesse caso, você poderá iniciar menos threads.
fonte
A resposta simples para sua pergunta é: eles usam memória virtual. tudo usa memória virtual, exceto alguns processos relacionados ao sistema operacional.
Por outro lado, quando seu thread (ou qualquer thread, em qualquer processo) está realmente em execução, ele está usando memória física. As páginas de memória associadas a esse processo são trocadas pela memória física, onde é o processador.
fonte
A memória virtual é sua RAM mais seu espaço de troca. Virtual significa apenas que o endereço que seu programa vê é diferente do endereço que o chip de RAM vê. Se você precisar acessar a memória em troca, o sistema operacional a moverá primeiro para a RAM. Se você não deseja trocar, desative-o. Se você tem RAM suficiente, não precisa realmente disso.
Dito isto, a menos que você tenha um processador de 10.000 núcleos, aumentar para 10.000 threads não é realmente uma "otimização". Quando você tiver threads suficientes para consumir todos os núcleos, mais um ou dois para quando esses threads estiverem bloqueados, a adição de mais threads diminuirá o desempenho devido à sobrecarga de comutação e falhas de cache. Você ainda pode querer usar mais threads, se isso simplificar a lógica do programa, mas você estará trocando o desempenho.
fonte
top
comando.Como outros explicaram, isso geralmente está errado. Um encadeamento é um recurso dispendioso , principalmente porque possui sua própria pilha de chamadas (normalmente, um megabyte) e porque é uma tarefa agendável pelo kernel. Os threads são ainda mais caros do que os descritores de arquivos abertos .
Leia Sistemas operacionais: Three Easy Pieces (livro didático disponível para download gratuito).
Como regra geral, você não deseja ter muitos threads, e certamente não muitos threads executáveis. O número de threads executáveis geralmente deve ser no máximo o número de núcleos (ou um pequeno múltiplo disso), portanto, cerca de uma dúzia no máximo. O número de threads em um processo pode ser um pouco maior. Portanto, a menos que você tenha um servidor muito expansivo (com muitos soquetes e núcleos de processador), não deseja ter mais de uma dúzia de threads executáveis e cem threads (a maioria deles ociosa) em seu processo (na área de trabalho) .
No Linux, threads e processos são muito semelhantes (já que ambos podem ser criados pelo clone (2) ) e ambos são tarefas agendadas pelo kernel. Na verdade, o agendador do kernel está agendando tarefas que podem ser threads dentro de algum processo com vários threads ou o thread principal único de um processo de thread único (nesse caso, você nomeará "processar" esse único thread) ou threads do kernel. Você provavelmente não deseja ter mais de mil tarefas agendáveis no total no seu sistema de desktop.
No Linux, um processo é simplesmente um grupo de threads compartilhando o mesmo espaço de endereço virtual (e compartilhando outras coisas, como tabela de descritores de arquivos, etc ...). Alguns processos têm apenas um encadeamento.
Um espaço de endereço virtual é definido pela Wikipedia como
(ver igualmente esta resposta explicando que a terminologia não é universal, e alguns documentação Microsoft usa um diferente e incompatível definição).
No Linux, proc (5) é útil para entender o espaço de endereço virtual de alguns processos. Tente ambos
cat /proc/self/maps
ecat /proc/$$/maps
em um terminal. Veja também isso , e pmap (1) e ps (1) e top (1) .Todos os programas de espaço do usuário estão executando em algum processo e usando memória virtual, portanto, todo processo tem seu próprio espaço de endereço virtual. A RAM física é um recurso gerenciado pelo kernel do Linux, e os aplicativos não têm acesso direto à RAM (exceto pelo mmap (2) -ing
/dev/mem
, consulte mem (4) ).Portanto, um processo não usa diretamente RAM. Ele usa memória virtual e possui seu próprio espaço de endereço virtual. O kernel usa paginação para gerenciar páginas físicas da RAM e fornecer o espaço de endereço virtual e as abstrações do processo . A qualquer momento (mesmo quando seu processo estiver ocioso ou em execução), o kernel poderá paginar algumas páginas (por exemplo, trocá-las no disco). O kernel está configurando o MMU (e lidando com exceções de hardware de falta de página em algum manipulador de interrupções , buscando a página do disco ou propagando uma falha de segmentação para o processo, consulte o sinal (7) )
Você pode ter threads verdes acima dos threads do sistema (mas as bibliotecas de threads verdes são difíceis de implementar e depurar). Veja as goroutines usadas no Go para um exemplo chique. Veja também setcontext (3) .
Às vezes, seu sistema pode experimentar debulhar . Isso acontece quando a memória virtual total (necessária para todos os processos) excede, por um grande fator, a RAM física disponível. Em seguida, seu computador não responde. Leia sobre o tamanho do conjunto residente , paginação por demanda , conjunto de trabalho , comprometimento excessivo de memória , ASLR .
Veja também -for Linux- fork (2) , clone (2) , mmap (2) , madvise (2) , posix_fadvise (2) , mlock (2) , execve (2) , credenciais (7) , pthreads (7) , futex (7) , recursos (7) .
fonte