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

42

O comentarista oferece as seguintes críticas aos tópicos ecológicos:

I was initially sold on the N:M model as a means of having event driven programming without the callback hell. You can write code that looks like pain old procedural code but underneath there's magic that uses userspace task switching whenever something would block. Sounds great. The problem is that we end up solving complexity with more complexity. swapcontext() and family are fairly strait-forward, the complexity comes from other unintended places.

All of a sudden you're forced to write a userspace scheduler and guess what it's really hard to write a scheduler that's going to do a better job that Linux's schedules that has man years of efforts put into it. Now you want your schedule to man N green threads to M physical threads so you have to worry about synchronization. Synchronization brings performance problems so you start now you're down a new lockless rabbit hole. Building a correct highly concurrent scheduler is no easy task.

Outra crítica está aqui :

A single process faking multiple threads has a lot of problems. One of them is that all the faked threads stall on any page fault.

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

    
por hawkeye 30.12.2013 / 04:58
fonte

1 resposta

62

Sou apenas um usuário casual do Google Go, portanto, aproveite o seguinte com um pouco de sal.

A Wikipédia define tópicos verdes como "threads agendados por uma máquina virtual (VM) em vez de nativamente pelo subjacente sistema operacional". Os encadeamentos verdes emulam ambientes multithread sem depender de nenhum recurso nativo do SO 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 possuem suporte a encadeamentos nativos.

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

Pessoas do Google cunharam o termo goroutine especialmente para evitar a confusão com outros mecanismos de concorrência (como corrotinas ou threads ou processos leves).

Naturalmente, 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 encadeamentos verdes (como implementado no início da JVM):

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

  • Chamadas do sistema e C não bloqueiam o agendador (todas as chamadas do sistema, não apenas as que suportam E / Ss multiplexadas em loops de evento). As implementações de encadeamentos verdes poderiam bloquear todo o processo quando uma chamada ao sistema de bloqueio fosse feita.

  • Copiando ou pilhas segmentadas. Em Go, não há necessidade de fornecer um tamanho máximo de pilha para a goroutine. A pilha cresce de forma incremental, conforme necessário. Uma conseqüência é que uma goroutine não requer muita memória (4KB-8KB), então 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 escrever um agendador de espaço de usuário: ele já é fornecido com o tempo de execução. É um software complexo, mas é o problema dos desenvolvedores Go, não dos usuários Go. Seu uso é transparente para os usuários do Go. Entre os desenvolvedores Go, Dmitri Vyukov é um especialista em programação lockfree / waitfree, e ele parece estar especialmente interessado em abordar os eventuais problemas de desempenho do agendador. A implementação atual do planejador não é perfeita, mas vai melhorar.

  • A sincronização traz problema e complexidade de desempenho: isso é parcialmente verdadeiro também com o Go. Mas observe que o modelo Go tenta promover o uso de canais e uma decomposição limpa do programa em goroutines concorrentes para limitar a complexidade da sincronização (ou seja, compartilhar dados por 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 gerador de perfis , e um detector de corrida .

  • Em relação a falha de página e "falsificação de vários segmentos", observe que o Go pode programar a linha de comando em vários encadeamentos do sistema. Quando um encadeamento é bloqueado por qualquer motivo (falha de página, bloqueio de chamadas do sistema), isso não impede que os outros encadeamentos continuem a programar e executar outras goroutines. Agora, é verdade que uma falha de página bloqueará o encadeamento do SO, com todas as goroutines supostamente agendadas neste encadeamento. No entanto, na prática, a memória heap do Google não deve ser trocada. Isso seria o mesmo em Java: as linguagens coletadas pelo lixo não acomodam muito bem a memória virtual. Se o seu programa deve lidar com falhas de página de uma forma graciosa, se provavelmente porque ele tem que gerenciar alguma memória fora do heap. Nesse caso, encapsular o código correspondente com funções de acesso C simplesmente resolverá o problema (porque, novamente, chamadas C ou bloqueio de chamadas do sistema nunca bloqueiam o agendador de tempo de execução Go).

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

    
por 30.12.2013 / 19:42
fonte