Postagem em destaque

A incrível velocidade do Go

Imagem
Um dos motivos que gosto do Go (a linguagem de programação, não o jogo), é que ele é extremamente rápido. E não estou falando de utilizar goroutines pois aí é covardia. Estamos migrando um sistema de Coldfusion para Go e PHP e uma das rotinas insere um registro no banco de dados no início e outra no fim do processo. Pense como se fosse um log, mas um log específico para essa rotina. Dessa forma: 2023-05-18 17:45:03. 687     ... [processaImagem] Incorporando imagem 2023-05-18 17:45:03. 688     ... [processaImagem] Imagem incorporada Entre o inicio e o final do processamento levou 1ms. Até aí, tudo bem, se não fosse o fato dessa tabela ter o campo timestamp como parte da chave primária. Se reparar, o tempo é definido em milissegundos. Com o Coldfusion esse processo dura cerca de 20ms. Simplesmente migrando para Go, o tempo caiu muito, para menos de 1ms e assim, começou a dar erro de chave duplicada. A solução? Depende, sempre depende. No nosso contexto, a mais simples foi feita, pois nã

Dicas Go - #1 - Goroutines

Já falei um pouco sobre concorrência em Go, mas percebi que não fui muito esclarecedor, por isso vou fazer uma outra abordagem, mais detalhada, sobre esse assunto. O código completo dos programas está no final do texto.

Vamos imaginar que você queira fazer um programa que faça acesso à uma API algumas vezes e retorne o resultado como string. Para não tornar o programa muito complexo, utilizei uma pesquisa fake, que simula um retorno e gasta  100 milissegundos. Ao rodar o programa sequencial.go, vemos na tela uma saída como a abaixo:


Como esperado, os resultados são listados em ordem, de "golang 0" à "golang 19". E o tempo gasto, pouco mais de 2s, também não é nenhuma surpresa (20 vezes 100 milissegundos mais algum tempo do resto do código).

A coisa começa a melhorar quando rodamos o programa concorrente.go.


O tempo gasto reduziu de 2s para 100ms. Qual é a mágica? São as goroutines! Se reparar bem, são poucas mudanças em relação ao código original (na verdade, essa é uma das formas que podemos usar as goroutines, mas é a que acho mais simples).

A primeira mudança é a criação de um canal com buffer de capacidade 4. Na prática, podemos enviar até 4 valores neste canal sem bloquear a goroutine. 

c := make(chan string, 4)

A segunda mudança é a chamada da função fakeSearch:

go func(j int) {
c <- fakeSearch("golang " + fmt.Sprintf("%d", j))
}(i)

Usamos uma função anônima para englobar a chamada em si, pois esta retorna um canal de string e não temos como chamar a função da forma abaixo:

go c <- fakeSearch("golang " + fmt.Sprintf("%d", j))

Por fim, temos que ler as respostas do canal, e para isso usamos um for para ler cada uma das respostas:

for i := 0; i < 20; i++ {
fmt.Printf("#%d - %s", i, <-c)
}

Aqui, o programa simplesmente joga o resultado que está no canal (<-c) para a tela, mas ele poderia ser armazenado num slice de strings por exemplo.

Código dos programas

Comentários

Postagens mais visitadas deste blog

Netflix não mostra ícone de streaming

Google Hacking

FTP não funciona no PHP