Slide 1

Slide 1 text

@nirev Guilherme Nogueira Segue o
 Fluxo Elixir's GenStage e Flow

Slide 2

Slide 2 text

Por quê? Flow e GenStage

Slide 3

Slide 3 text

Processamento de Dados Flow e GenStage

Slide 4

Slide 4 text

Processamento de Dados Flow e GenStage • Processamento de Logs • Indexação de dados para busca • Algoritmos de Recomendação • Dashboards em tempo real • etc…

Slide 5

Slide 5 text

Processamento de Dados 1.ávido 2.preguiçoso 3.??? 4.PROFIT

Slide 6

Slide 6 text

Processamento de Dados 1.ávido 2.preguiçoso 3.concorrente 4.distribuído

Slide 7

Slide 7 text

Ávido (Eager)

Slide 8

Slide 8 text

Ávido File.read!("path/to/some/file") |> Enum.flat_map(&String.split(&1, " ")) |> Enum.reduce(%{}, fn word, acc -> Map.update(acc, word, 1, & &1 + 1) end) |> Enum.to_list()

Slide 9

Slide 9 text

Ávido • Simples • Tudo em memória • Lento para arquivos muito grandes • 0% de concorrência File.read!("path/to/some/file") |> Enum.flat_map(&String.split(&1, " ")) |> Enum.reduce(%{}, fn word, acc -> Map.update(acc, word, 1, & &1 + 1) end) |> Enum.to_list()

Slide 10

Slide 10 text

Preguiçoso (Lazy)

Slide 11

Slide 11 text

Preguiçoso File.stream!("path/to/some/file") |> Stream.flat_map(&String.split(&1, " ")) |> Enum.reduce(%{}, fn word, acc -> Map.update(acc, word, 1, & &1 + 1) end) |> Enum.to_list()

Slide 12

Slide 12 text

Preguiçoso • Melhor, um de cada vez • Menos uso de memória • Ainda lento para arquivos muito grandes • 0% de concorrência File.stream!("path/to/some/file") |> Stream.flat_map(&String.split(&1, " ")) |> Enum.reduce(%{}, fn word, acc -> Map.update(acc, word, 1, & &1 + 1) end) |> Enum.to_list()

Slide 13

Slide 13 text

Concorrente

Slide 14

Slide 14 text

Concorrente File.stream!("path/to/some/file") |> Flow.from_enumerable() |> Flow.flat_map(&String.split(&1, " ")) |> Flow.partition() |> Flow.reduce(fn -> %{} end, fn word, acc -> Map.update(acc, word, 1, & &1 + 1) end) |> Enum.to_list()

Slide 15

Slide 15 text

Concorrente • Agora, sim! Multi-processos • Perde noção de ordem File.stream!("path/to/some/file") |> Flow.from_enumerable() |> Flow.flat_map(&String.split(&1, " ")) |> Flow.partition() |> Flow.reduce(fn -> %{} end, fn word, acc -> Map.update(acc, word, 1, & &1 + 1) end) |> Enum.to_list()

Slide 16

Slide 16 text

Concorrente • Agora, sim! Multi-processos • Perde noção de ordem File.stream!("path/to/some/file") |> Flow.from_enumerable() |> Flow.flat_map(&String.split(&1, " ")) |> Flow.partition() |> Flow.reduce(fn -> %{} end, fn word, acc -> Map.update(acc, word, 1, & &1 + 1) end) |> Enum.to_list()

Slide 17

Slide 17 text

Flow

Slide 18

Slide 18 text

Flow • Um meio de expressar processamento em cima de coleções (tipo Enum e Stream), mas feitas em paralelo com GenStage • Funciona com dados finitos e não-finitos • Inspirado no Apache Spark

Slide 19

Slide 19 text

GenStage

Slide 20

Slide 20 text

GenStage • É um behaviour • Feito para trocar dados entre “estágios” • de forma transparente • e com back-pressure

Slide 21

Slide 21 text

GenStage Producer/ Consumer Producer Producer/ Consumer Consumer

Slide 22

Slide 22 text

GenStage • O Consumidor se subscreve ao Produtor • Quem dita a velocidade é o Consumidor • Produtor pode enviar à vários Consumidores • Diferentes políticas para despacho aos Consumidores

Slide 23

Slide 23 text

GenStage Producer Consumer Pede X Recebe no máximo X

Slide 24

Slide 24 text

GenStage Producer Consumer Pede X Recebe no máximo X max_demand: máximo de itens que o consumidor pede min_demand: mínimo de itens, quando atingir esse número pede mais

Slide 25

Slide 25 text

GenStage Producer 1 2,4 3 Despacho 1,2,3,4 DemandDispatcher

Slide 26

Slide 26 text

GenStage Producer 1,2 1,2 1,2 Despacho 1,2 BroadcastDispatcher

Slide 27

Slide 27 text

GenStage Producer 1,4 2,5 3,6 Despacho 1,2,3,4,5,6 PartitionDispatcher rem(e,3)

Slide 28

Slide 28 text

GenStage Exemplo (https://github.com/nirev/gen_stage_example)

Slide 29

Slide 29 text

Distribuído

Slide 30

Slide 30 text

Distribuído • Não tem ainda • Faltam mecanismos de garantias no Flow • Precisa mesmo distribuir? • Mais informações em breve…

Slide 31

Slide 31 text

Conclusão

Slide 32

Slide 32 text

Conclusão • Pipelines de dados como “cidadãos" do Elixir • API muito familiar pra quem já usou outros frameworks • Bastante promissor • Não tem garantias ainda: 
 ou seja, não usar para processar pagamento ;D

Slide 33

Slide 33 text

Thanks! https://xerpa.recruiterbox.com/ Estamos contratando! @nirev Guilherme Nogueira

Slide 34

Slide 34 text

Referências • https://hexdocs.pm/gen_stage • https://hexdocs.pm/flow • https://www.youtube.com/watch?v=aZuY5-2lwW4 • https://www.youtube.com/watch?v=IBcLOxW1Zgs • http://teamon.eu/2016/tuning-elixir-genstage-flow-pipeline-processing/ • https://blog.discordapp.com/how-discord-handles-push-request-bursts-of-over-a-million-per- minute-with-elixirs-genstage-8f899f0221b4 Documentação e Palestras Relatos de Uso