As piscinas de goroutine go-langs são apenas fios verdes?


47

O comentarista aqui oferece as seguintes críticas aos fios verdes:

Inicialmente, fui vendido no modelo N: M como um meio de ter programação orientada a eventos sem o inferno de retorno de chamada. Você pode escrever um código parecido com um código processual antigo, mas por baixo há uma mágica que usa a alternância de tarefas no espaço do usuário sempre que algo bloqueia. Parece bom. O problema é que acabamos resolvendo a complexidade com mais complexidade. swapcontext () e family são bastante diretos, a complexidade vem de outros lugares não desejados.

De repente, você é forçado a escrever um agendador de espaço do usuário e adivinhar o que é realmente difícil escrever um agendador que faça um trabalho melhor do que os agendamentos do Linux, que têm muitos anos de esforço nele. Agora você deseja que sua programação use N threads verdes para M threads físicos, para que você tenha que se preocupar com a sincronização. A sincronização traz problemas de desempenho, então você começa agora que está em uma nova toca de coelho sem bloqueio. Criar um planejador altamente concorrente correto não é uma tarefa fácil.

Outra crítica está aqui :

Um único processo de falsificação de vários encadeamentos apresenta muitos problemas. Uma delas é que todos os encadeamentos falsos são interrompidos por qualquer falha de página.

A minha pergunta é - são goroutines go-Lang (para um conjunto padrão) apenas tópicos verdes? Se sim - eles abordam as críticas acima?

Respostas:


67

Como sou apenas um usuário casual do Go, faça o seguinte com um pouco de sal.

A Wikipedia define threads verdes como "threads agendados por uma máquina virtual (VM) em vez de nativamente pelo sistema operacional subjacente". Os threads verdes emulam ambientes multithread sem confiar em nenhum recurso nativo do sistema operacional e são gerenciados no espaço do usuário em vez do espaço do kernel, permitindo que trabalhem em ambientes que não têm suporte de thread nativo.

Go (ou mais exatamente as duas implementações existentes) é um idioma que produz apenas código nativo - não usa uma VM. Além disso, o planejador nas implementações de tempo de execução atuais depende de threads no nível do SO (mesmo quando GOMAXPROCS = 1). Então, acho que falar de linhas verdes para o modelo Go é um pouco abusivo.

Go people cunharam o termo goroutine especialmente para evitar a confusão com outros mecanismos de simultaneidade (como corotinas ou threads ou processos leves).

Obviamente, o Go suporta um modelo de encadeamento M: N, mas parece muito mais próximo do modelo de processo Erlang do que do modelo de encadeamento verde Java.

Aqui estão alguns benefícios do modelo Go sobre threads verdes (conforme implementado no início da JVM):

  • Vários núcleos ou CPUs podem ser efetivamente usados, de forma transparente para o desenvolvedor. Com o Go, o desenvolvedor deve cuidar da simultaneidade. O tempo de execução Go cuidará do paralelismo. As implementações de encadeamentos verdes de Java não foram escalonadas em vários núcleos ou CPUs.

  • As chamadas do sistema e C não são bloqueadas para o planejador (todas as chamadas do sistema, não apenas as que suportam E / S multiplexadas em loops de eventos). As implementações de threads verdes poderiam bloquear todo o processo quando uma chamada do sistema de bloqueio era feita.

  • Cópia ou pilhas segmentadas. No Go, não há necessidade de fornecer um tamanho máximo de pilha para a goroutine. A pilha cresce incrementalmente conforme necessário. Uma conseqüência é que uma goroutine não requer muita memória (4KB-8KB); portanto, um grande número delas pode ser gerado com alegria. O uso de goroutine pode, portanto, ser difundido.

Agora, para abordar as críticas:

  • Com o Go, você não precisa gravar um planejador de espaço do usuário: ele já é fornecido com o tempo de execução. É um software complexo, mas é o problema dos desenvolvedores do Go, não dos usuários do Go. Seu uso é transparente para usuários do Go. Entre os desenvolvedores do Go, Dmitri Vyukov é especialista em programação sem bloqueio / espera, e ele parece estar especialmente interessado em resolver os eventuais problemas de desempenho do planejador. A implementação atual do planejador não é perfeita, mas irá melhorar.

  • A sincronização traz problemas e complexidade de desempenho: isso também é parcialmente verdade com o Go. Mas observe que o modelo Go tenta promover o uso de canais e uma decomposição limpa do programa em goroutines simultâneas para limitar a complexidade da sincronização (isto é, compartilhar dados pela comunicação, em vez de compartilhar a memória para se comunicar). A propósito, a implementação Go de referência fornece várias ferramentas para resolver problemas de desempenho e simultaneidade, como um criador de perfil e um detector de corrida .

  • Em relação à falha de página e "vários threads falsos", observe que o Go pode agendar goroutine em vários threads do sistema. Quando um thread é bloqueado por qualquer motivo (falha na página, bloqueio de chamadas do sistema), isso não impede que os outros threads continuem a agendar e executar outras goroutines. Agora, é verdade que uma falha de página bloqueará o encadeamento do SO, com todas as goroutines agendadas para esse encadeamento. No entanto, na prática, a memória heap Go não deve ser trocada. Isso seria o mesmo em Java: as linguagens de coleta de lixo não acomodam muito bem a memória virtual. Se o seu programa deve lidar com falhas de página de maneira simples, provavelmente porque precisa gerenciar alguma memória fora da pilha. Nesse caso,

Portanto, na IMO, as goroutines não são linhas verdes, e a linguagem Go e a implementação atual abordam principalmente essas críticas.


1
Uma resposta excelente e detalhada à pergunta :)
Tuxdude

1
Adoro esta resposta, mas você tem alguma referência a como / quando os threads do sistema operacional são criados?
Lars

1
Uma das maiores desvantagens do Go Language é que ele cria um thread do Kernel para cada chamada do sistema de bloqueio!
user1870400

8
Observe que o artigo “thread verde” na Wikipedia foi alterado para o estado “threads agendados por uma biblioteca de tempo de execução ou máquina virtual (VM)”; o que significa que, por essa definição, sua resposta não estaria mais correta, como o tempo de execução do Go faz o agendamento / gerenciamento. Eu acho que é mais útil definir threads verdes como threads do espaço do usuário que contrastam com threads do SO. E então, sim, as goroutines são linhas verdes, com certeza.
mknecht

1
Segundo que @mknecht. Não é sobre a VM, é sobre tempo de execução. E o Go definitivamente tem um tempo de execução. (que gerencia o modelo de encadeamento e a coleta de lixo).
Tim Harper
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.