O documento discute princípios de programação concorrente em Ruby, incluindo: 1) o que é concorrência e por que escrever código concorrente; 2) diferentes modelos de concorrência como multiprocessos, multithreading e fibras; 3) desafios de escrever código concorrente como o GIL e deadlocks.
2. Agenda
➢
O que é concorrência ?
➢
Pra quê escrever código concorrente ?
➢
(Breve) Explicação dos diferentes modelos de concorrência
➢
Por que escrever código concorrente é dificil ?
➢
O que é o tão odiado GIL
➢
Abstrações úteis que facilitam sua vida multithreaded
➢
Exemplo de como usamos isso tudo em uma app real &
lições aprendidas
3. O que é concorrência?
➢
Concorrência, assincronia e paralelismo são coisas relacionadas mas
que muita gente as confunde.
➢
“Concurrency is when two tasks can start, run, and complete in
overlapping time periods. It doesn’t necessarily mean they’ll ever
both be running at the same instant. E.g. Multitasking in a single
core machine”
➢
“Parallelism is when tasks literally run at the same time, e.g. on a
multicore processor or SIMD instructions”
- Sun’s Multithreaded programming guide
4. O que é concorrência?
➢
Assincronia significa que o resultado de uma
computação não esta disponível imediatamente
após a avaliação.
➢
Significa que a maquina pode fazer outras coisas
enquanto espera essa computação terminar e
eventualmente no futuro fazer uso do resultado da
mesma
5. Pra quê escrever código concorrente
➢
Concorrência possibilita assincronia e paralelismo
➢
Libera o CPU para fazer outras coisas enquanto
espera por IO (http, banco, rede, disco, etc.) oferece
mais performance. E.g. você poderá servir os
requests de 30 usuários ao mesmo tempo ao invés
de 1.
6. Diferentes modelos de concorrência
➢
Multiprocesses (resque, unicorn)
➢
Multithreading (sidekiq)
➢
Fibers (Ruby tem fibers!)
➢
Corroutines
➢
Actors (Celluloid)
➢
Outras bruxarias que eu não manjo(process calculi)
7. Multithreading
➢
Threads, assim como processos, são coisas oferecidas
pelo SO.
➢
Mutexes ~
➢
Deadlocks ~
➢
Thread#join ~
➢
Comportamento diferente com exceptions (e.g.
streaming do log no package-installer)
12. Pausa para o GIL
➢
O GIL (Global Interpreter Lock) impede que código
ruby rode em paralelo.
➢
A unica ocasião em que é seguro para o GIL deixar
coisas acontecerem em paralelo é com IO.
➢
Se sua vida é IO-bound, isso é o que importa.
17. Multithreading – Evite Thread.new
➢
É uma boa idéia não usar threads diretamente.
➢
Existem várias abstrações melhores e mais seguras
para expressar a task que você tem em mãos.
➢
Uma referência excelente é a lib do java
java.util.concurrent. No mundo Ruby existe a gem
concurrent-ruby que implementa parte do
java.util.concurrent.
31. Caso de uso - Hodor
➢
Dahora! Tudo funcionava....
➢
Mas ai resolvemos medir:
Tempo atualizando status dos eventos na “fila”
Tempo fazendo o processamento dos eventos
37. Lições aprendidas
➢
Por favor, atualizem as versões dos drivers de banco.
TinyTds ~ 0.5 tinha zilhares de issues relacionadas
a multi-threading.
➢
38. Lições aprendidas
➢
Metricas são muito mais legais que logs
➢
http://webleela.service.ita.consul.locaweb.com.br/inde
x.html#/dashboard/db/heisenberghodor
40. ➢
Figura pare pense ?
➢
➢
Para evitar problemas como o da foto do mimi triste:
➢
1. Não use concorrência
➢
2. Se for usar, não compartilhe nada. Não decida usar
antes de MEDIR e ter certeza que você realmente
precisa.
➢
3. Se tiver que compartilhar, tomar muito cuidado pra
sincronizar o acesso