Elixiroflife-devinsantos2015-151201114117-lva1-app6891.pdf

  • Uploaded by: Carlos Amorim
  • 0
  • 0
  • June 2020
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Elixiroflife-devinsantos2015-151201114117-lva1-app6891.pdf as PDF for free.

More details

  • Words: 1,555
  • Pages: 106
ELIXIR OF LIFE

http://www.efeitmusic.com/efeitimages/Elixeroflife.jpg

ELIXIR OF LIFE

Fabio Akita http://www.efeitmusic.com/efeitimages/Elixeroflife.jpg

@akitaonrails

Intel1Processors1Transistor1Count 8,000,000,000

Duo-core + GPU Core i7 Broadwell-U

7,000,000,000

14 nm

6,000,000,000

18-core Xeon Haswell-E5 22 nm

5,000,000,000

15-core Xeon Ivy Bridge-EX

4,000,000,000

8-core Itanium Poulson

3,000,000,000

32 nm

Apple A8X 20 nm

2,000,000,000

Six-core Xeon 7400

1,000,000,000

Itanium 2 Intel 4004 10 µm

0 1965

1970

1975

Intel 80386 1980

1985

Pentium

Apple A8

Apple A7

0.8 µm

1990

1995

2000

2005

2010

2015

2020

Deveríamos estar em 9Ghz 16nm transistors quantum tunneling leakage, 1-3nm http://en.wikipedia.org/wiki/Quantum_tunnelling

EVENTOS!

Node + Express (8 x 200)

Node + Express (8 x 200)

Elixir + Phoenix (8 x 200)

Elixir + Phoenix (8 x 200)

Node + Express (1 x 10 + sleep(1))

Node + Express (1 x 10 + sleep(1))

Elixir + Phoenix (2 x 400 + sleep(1000))

Elixir + Phoenix (2 x 400 + sleep(1000))

LOW LATENCY

http://yarivsblog.blogspot.com.br/2008/05/erlang-vs-scala.html

Scala has two types of Actors: thread-based and event based. Thread based actors execute in heavyweight OS threads. They never block each other, but they don't scale to more than a few thousand actors per VM. Event-based actors are simple objects. They are very lightweight, and, like Erlang processes, you can spawn millions of them on a modern machine. The difference with Erlang processes is that within each OS thread, event based actors execute sequentially without preemptive scheduling. This makes it possible for an event-based actor to block its OS thread for a long period of time (perhaps indefinitely).

começo de novembro

Rackspace 15 GB I/O v1 - these machines have 15GB RAM and 4 cores. Rackspace kindly let us use 3 of these servers for our benchmarks free of charge.

OnMetal I/O which had 128GB RAM and showed 40 cores in htop.

começo de novembro

Rackspace 15 GB I/O v1 - these machines have 15GB RAM and 4 cores. Rackspace kindly let us use 3 of these servers for our benchmarks free of charge.

OnMetal I/O which had 128GB RAM and showed 40 cores in htop.

CASES

“Since cut-over of the first nodes in British Telecom's network in January 2002 only one minor fault has occurred, resulting in 99.9999999% availability.” “The network performance has been so reliable that there is almost a risk that our field engineers do not learn maintenance skills.” Bernt Nilsson - director of Ericsson’s Next Generation Systems program

http://www.erlang.org/download/armstrong_thesis_2003.pdf

BÁSICO …

iex --sname fabio --cookie secret_token

iex --sname akita --cookie secret_token

Node.list

Node.ping(:"akita@MacBook-Pro")

defmodule Greeting do

def say do

IO.puts "CALLED"

"Hello World from #{Node.self}"

end

end

:rpc.call(:"fabio@MacBook-Pro", Greeting, :say, [])

iex --name [email protected] --cookie secret_token

iex --name [email protected] --cookie secret_token

iex --sname fabio --cookie secret_token

iex --sname akita --cookie secret_token

Node.list

Node.ping(:"akita@MacBook-Pro")

defmodule Greeting do

def say do

IO.puts "CALLED"

"Hello World from #{Node.self}"

end

end

:rpc.call(:"fabio@MacBook-Pro", Greeting, :say, [])

iex --name [email protected] --cookie secret_token

iex --name [email protected] --cookie secret_token

PEER-TO-PEER NETWORKING

Matching

a = 20

defmodule Teste do

def teste do

a = 40

IO.puts("Hello #{a}")

end

end

IO.puts(a)

a = 20

^a = 40

[a, b, c] = [a, 2, 3]

{:ok, message} = {:ok, "world"}

{:ok, [hello: message]} = {:ok, [hello: "world"]}

Matching

a = 20

defmodule Teste do

def teste do

a = 40

IO.puts("Hello #{a}")

end

end

IO.puts(a)

a = 20

^a = 40

[a, b, c] = [a, 2, 3]

{:ok, message} = {:ok, "world"}

{:ok, [hello: message]} = {:ok, [hello: "world"]}

PATTERN MATCHING

Call by pattern

defmodule Greeting do

def hello([name: name]) do

"Hey, #{name}"

end

def hello([lastname: lastname]) do

"Hello, Mr #{lastname}"

end

end

Greeting.hello(name: "Fabio")

Greeting.hello(lastname: "Akita")

Call by pattern

defmodule Greeting do

def hello([name: name]) do

"Hey, #{name}"

end

def hello([lastname: lastname]) do

"Hello, Mr #{lastname}"

end

end

Greeting.hello(name: "Fabio")

Greeting.hello(lastname: "Akita")

CALL BY PATTERN

Spawn

self

send(self, :hello)

flush

send(self, :hello)

receive do

:hello -> IO.puts("hello")

end

defmodule Bar do

def say do

receive do

{:ok, message} ->

IO.puts("Hello #{message}")

say

end

end

end

Spawn

self

send(self, :hello)

flush

send(self, :hello)

receive do

:hello -> IO.puts("hello")

end

defmodule Bar do

def say do

receive do

{:ok, message} ->

IO.puts("Hello #{message}")

say

end

end

end

PROCESS (GREEN THREAD)

Green Thread = Co-Rotina que pode ser suspensa

2000 reduções

single thread por core/scheduler

1 run-queue

Processes

Process.list

defmodule Foo do

def counter(n) do

receive do

{:read, from} ->

send(from, n)

counter(n + 1)

end

end

end

pid = spawn(fn -> Foo.counter(2) end)

list = Enum.map((1..500_000), fn n ->

spawn(fn -> Foo.counter(n) end)

end)

Processes

Process.list

defmodule Foo do

def counter(n) do

receive do

{:read, from} ->

send(from, n)

counter(n + 1)

end

end

end

pid = spawn(fn -> Foo.counter(2) end)

list = Enum.map((1..500_000), fn n ->

spawn(fn -> Foo.counter(n) end)

end)

ASYNCHRONOUS

EXCEPTIONS

ESTADO IMUTAVEL

SEM ESTADO GLOBAL

ASYNCHRONOUS

EXCEPTIONS

ESTADO IMUTAVEL

SEM ESTADO GLOBAL

Trap Exits (http://eddwardo.github.io/elixir/links/2015/11/04/links-in-elixir/)

defmodule Foo do

def counter(n) do

receive do

{:read, from} ->

send(from, n)

counter(n + 1)

{:bla} ->

raise "I'm a bug!"

end

end

end

pid = spawn(fn -> Foo.counter(2) end)

Process.alive?(pid)

Process.link(pid)

Process.exit(pid, :kill)

pid = spawn(fn -> Foo.counter(2) end)

Trap Exits (http://eddwardo.github.io/elixir/links/2015/11/04/links-in-elixir/)

defmodule Foo do

def counter(n) do

receive do

{:read, from} ->

send(from, n)

counter(n + 1)

{:bla} ->

raise "I'm a bug!"

end

end

end

pid = spawn(fn -> Foo.counter(2) end)

Process.alive?(pid)

Process.link(pid)

Process.exit(pid, :kill)

pid = spawn(fn -> Foo.counter(2) end)

Observer/Schedulers

defmodule Foo do

def counter(n) do

receive do

{:read, from} ->

send(from, n)

counter(n + 1)

end

end

end

list = Enum.map((1..100_000), fn n ->

spawn(fn -> Foo.counter(n) end)

end)

Enum.each(list, fn pid -> Process.exit(pid, :kill) end)

defmodule Repeat do

Observer/Schedulers

defmodule Foo do

def counter(n) do

receive do

{:read, from} ->

send(from, n)

counter(n + 1)

end

end

end

list = Enum.map((1..100_000), fn n ->

spawn(fn -> Foo.counter(n) end)

end)

Enum.each(list, fn pid -> Process.exit(pid, :kill) end)

defmodule Repeat do

ACTORS!

GenServer Simple

defmodule Stack do

use GenServer

# Callbacks

def handle_call(:pop, _from, [head|tail]) do

{:reply, head, tail}

end

def handle_cast({:push, item}, state) do

{:noreply, [item|state]}

end

end

{:ok, pid} = GenServer.start_link(Stack, [:hello])

GenServer.call(pid, :pop)

GenServer.cast(pid, {:push, :world})

GenServer.cast(pid, {:push, :blabla})

GenServer.call(pid, :pop)

GenServer Simple

defmodule Stack do

use GenServer

# Callbacks

def handle_call(:pop, _from, [head|tail]) do

{:reply, head, tail}

end

def handle_cast({:push, item}, state) do

{:noreply, [item|state]}

end

end

{:ok, pid} = GenServer.start_link(Stack, [:hello])

GenServer.call(pid, :pop)

GenServer.cast(pid, {:push, :world})

GenServer.cast(pid, {:push, :blabla})

GenServer.call(pid, :pop)

defmodule Stack do

use GenServer

# Public API

def pop(server), do: GenServer.call(server, :pop)

def push(server, item), do: GenServer.cast(server, {:push, item})

# Callbacks

def handle_call(:pop, _from, [head|tail]) do

{:reply, head, tail}

end

def handle_cast({:push, item}, state) do

{:noreply, [item|state]}

end

end

{:ok, pid} = GenServer.start_link(Stack, ["John"])

Stack.push(pid, "Woo")

defmodule Stack do

use GenServer

# Public API

def pop(server), do: GenServer.call(server, :pop)

def push(server, item), do: GenServer.cast(server, {:push, item})

# Callbacks

def handle_call(:pop, _from, [head|tail]) do

{:reply, head, tail}

end

def handle_cast({:push, item}, state) do

{:noreply, [item|state]}

end

end

{:ok, pid} = GenServer.start_link(Stack, ["John"])

Stack.push(pid, "Woo")

GenServer Kill

defmodule Stack do

use GenServer

def start_link(state, opts \\ []) do

GenServer.start_link(__MODULE__, [state], name: __MODULE__)

end

def pop, do: GenServer.call(__MODULE__, :pop)

def push(item), do: GenServer.cast(__MODULE__, {:push, item})

# Callbacks

def handle_call(:pop, _from, [head|tail]) do

{:reply, head, tail}

end

def handle_cast({:push, item}, state) do

{:noreply, [item|state]}

GenServer Kill

defmodule Stack do

use GenServer

def start_link(state, opts \\ []) do

GenServer.start_link(__MODULE__, [state], name: __MODULE__)

end

def pop, do: GenServer.call(__MODULE__, :pop)

def push(item), do: GenServer.cast(__MODULE__, {:push, item})

# Callbacks

def handle_call(:pop, _from, [head|tail]) do

{:reply, head, tail}

end

def handle_cast({:push, item}, state) do

{:noreply, [item|state]}

Supervisor - Restart

defmodule StackSupervisor do

use Supervisor

def start_link do

Supervisor.start_link(__MODULE__, [])

end

def init([]) do

children = [

worker(Stack, ["hello"])

]

supervise(children, strategy: :one_for_one)

end

end

StackSupervisor.start_link

Supervisor - Restart

defmodule StackSupervisor do

use Supervisor

def start_link do

Supervisor.start_link(__MODULE__, [])

end

def init([]) do

children = [

worker(Stack, ["hello"])

]

supervise(children, strategy: :one_for_one)

end

end

StackSupervisor.start_link

SUPERVISOR TREE (supervisor - supervisees/workers)

OTP (Open Telecom Platform)

Phoenix - Observer

Applications - Micro Services

Phoenix - Observer

Applications - Micro Services

MICRO “YOCTO” SERVICES (Micro > Nano > Pico > Femto > Atto > Zepto > Yocto)



Map, Structs, Records, Comprehensions



Map, Structs, Records, Comprehensions



Testable Docs



Map, Structs, Records, Comprehensions



Testable Docs



TypeSpecs/Behaviors



Map, Structs, Records, Comprehensions



Testable Docs



TypeSpecs/Behaviors



Agents/Tasks/GenEvent



Map, Structs, Records, Comprehensions



Testable Docs



TypeSpecs/Behaviors



Agents/Tasks/GenEvent



Sigils/Macros/DSLs



Map, Structs, Records, Comprehensions



Testable Docs



TypeSpecs/Behaviors



Agents/Tasks/GenEvent



Sigils/Macros/DSLs



ETS/DETS/Mnesia

/

shared mutable global state Blocking Event Loop

Rust

/

Low Level Async in progress No coroutines

Go

Suture (OTP Clone)

goroutines sem ID shared mutable state static signatures

Scala

Akka (OTP Clone)

shared mutable state static signatures

Clojure

Pulsar / Quasar

Javascript

Almost Erlang-like Process JVM limitations

Go http://www.jerf.org/iri/post/2930

Scala http://yarivsblog.blogspot.com.br/2008/05/erlang-vs-scala.html

Clojure http://blog.paralleluniverse.co/2013/05/02/quasar-pulsar/

Scala has two types of Actors: thread-based and event based. Thread based actors execute in heavyweight OS threads. They never block each other, but they don't scale to more than a few thousand actors per VM. Event-based actors are simple objects. They are very lightweight, and, like Erlang processes, you can spawn millions of them on a modern machine. The difference with Erlang processes is that within each OS thread, event based actors execute sequentially without preemptive scheduling. This makes it possible for an event-based actor to block its OS thread for a long period of time (perhaps indefinitely).

“quase” …

Erlang:

DONE! (30 anos)

APRENDENDO

OBRIGADO [email protected]

More Documents from "Carlos Amorim"