ELIXIR OF LIFE
http://www.efeitmusic.com/efeitimages/Elixeroflife.jpg
Fabio Akita
ELIXIR OF LIFE
http://www.efeitmusic.com/efeitimages/Elixeroflife.jpg
@akitaonrails
0
1,000,000,000
2,000,000,000
3,000,000,000
4,000,000,000
5,000,000,000
6,000,000,000
7,000,000,000
8,000,000,000
1965 1970 1975 1980 1985 1990 1995 2000 2005 2010 2015 2020
Intel1Processors1Transistor1Count
Intel 4004
10 µm Intel 80386 Pentium
0.8 µm
Itanium 2
Six-core Xeon 7400
8-core Itanium Poulson
32 nm
18-core Xeon Haswell-E5
22 nm
15-core Xeon Ivy Bridge-EX
Duo-core + GPU Core i7 Broadwell-U
14 nm
Apple A7
Apple A8
Apple A8X
20 nm
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 fabio@192.168.1.4 --cookie secret_token

iex --name akita@192.168.1.4 --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 fabio@192.168.1.4 --cookie secret_token

iex --name akita@192.168.1.4 --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
Javascript /
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
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
become@codeminer42.com
OBRIGADO

"Elixir of Life" - Dev In Santos

  • 1.
  • 2.
    Fabio Akita ELIXIR OFLIFE http://www.efeitmusic.com/efeitimages/Elixeroflife.jpg
  • 3.
  • 9.
    0 1,000,000,000 2,000,000,000 3,000,000,000 4,000,000,000 5,000,000,000 6,000,000,000 7,000,000,000 8,000,000,000 1965 1970 19751980 1985 1990 1995 2000 2005 2010 2015 2020 Intel1Processors1Transistor1Count Intel 4004 10 µm Intel 80386 Pentium 0.8 µm Itanium 2 Six-core Xeon 7400 8-core Itanium Poulson 32 nm 18-core Xeon Haswell-E5 22 nm 15-core Xeon Ivy Bridge-EX Duo-core + GPU Core i7 Broadwell-U 14 nm Apple A7 Apple A8 Apple A8X 20 nm
  • 10.
    Deveríamos estar em9Ghz 16nm transistors quantum tunneling leakage, 1-3nm http://en.wikipedia.org/wiki/Quantum_tunnelling
  • 12.
  • 15.
    Node + Express(8 x 200)
  • 16.
    Node + Express(8 x 200)
  • 17.
  • 18.
  • 19.
    Node + Express(1 x 10 + sleep(1))
  • 20.
    Node + Express(1 x 10 + sleep(1))
  • 21.
    Elixir + Phoenix(2 x 400 + sleep(1000))
  • 22.
    Elixir + Phoenix(2 x 400 + sleep(1000))
  • 23.
    LOW LATENCY http://yarivsblog.blogspot.com.br/2008/05/erlang-vs-scala.html Scala hastwo 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).
  • 24.
    começo de novembro Rackspace15 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.
  • 25.
    começo de novembro Rackspace15 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.
  • 27.
  • 29.
    “Since cut-over ofthe 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
  • 39.
  • 40.
  • 41.
    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 fabio@192.168.1.4 --cookie secret_token iex --name akita@192.168.1.4 --cookie secret_token
  • 42.
    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 fabio@192.168.1.4 --cookie secret_token iex --name akita@192.168.1.4 --cookie secret_token
  • 43.
  • 44.
    Matching a = 20 defmoduleTeste 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"]}
  • 45.
    Matching a = 20 defmoduleTeste 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"]}
  • 46.
  • 47.
    Call by pattern defmoduleGreeting 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")
  • 48.
    Call by pattern defmoduleGreeting 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")
  • 49.
  • 50.
    Spawn self send(self, :hello) flush send(self, :hello) receivedo :hello -> IO.puts("hello") end defmodule Bar do def say do receive do {:ok, message} -> IO.puts("Hello #{message}") say end end end
  • 51.
    Spawn self send(self, :hello) flush send(self, :hello) receivedo :hello -> IO.puts("hello") end defmodule Bar do def say do receive do {:ok, message} -> IO.puts("Hello #{message}") say end end end
  • 52.
    PROCESS (GREEN THREAD) Green Thread= Co-Rotina que pode ser suspensa 2000 reduções single thread por core/scheduler 1 run-queue
  • 53.
    Processes Process.list defmodule Foo do defcounter(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)
  • 54.
    Processes Process.list defmodule Foo do defcounter(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)
  • 55.
  • 56.
  • 57.
    Trap Exits (http://eddwardo.github.io/elixir/links/2015/11/04/links-in-elixir/) defmoduleFoo 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)
  • 58.
    Trap Exits (http://eddwardo.github.io/elixir/links/2015/11/04/links-in-elixir/) defmoduleFoo 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)
  • 59.
    Observer/Schedulers defmodule Foo do defcounter(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
  • 60.
    Observer/Schedulers defmodule Foo do defcounter(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
  • 61.
  • 62.
    GenServer Simple defmodule Stackdo 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)
  • 63.
    GenServer Simple defmodule Stackdo 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)
  • 64.
    defmodule Stack do useGenServer # 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")
  • 65.
    defmodule Stack do useGenServer # 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")
  • 66.
    GenServer Kill defmodule Stackdo 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]}
  • 67.
    GenServer Kill defmodule Stackdo 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]}
  • 68.
    Supervisor - Restart defmoduleStackSupervisor 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
  • 69.
    Supervisor - Restart defmoduleStackSupervisor 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
  • 70.
    SUPERVISOR TREE (supervisor -supervisees/workers)
  • 71.
  • 72.
  • 73.
  • 74.
    MICRO “YOCTO” SERVICES (Micro > Nano> Pico > Femto > Atto > Zepto > Yocto)
  • 79.
    • Map, Structs,Records, Comprehensions
  • 80.
    • Map, Structs,Records, Comprehensions • Testable Docs
  • 81.
    • Map, Structs,Records, Comprehensions • Testable Docs • TypeSpecs/Behaviors
  • 82.
    • Map, Structs,Records, Comprehensions • Testable Docs • TypeSpecs/Behaviors • Agents/Tasks/GenEvent
  • 83.
    • Map, Structs,Records, Comprehensions • Testable Docs • TypeSpecs/Behaviors • Agents/Tasks/GenEvent • Sigils/Macros/DSLs
  • 84.
    • Map, Structs,Records, Comprehensions • Testable Docs • TypeSpecs/Behaviors • Agents/Tasks/GenEvent • Sigils/Macros/DSLs • ETS/DETS/Mnesia
  • 85.
    Javascript / shared mutableglobal 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 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).
  • 86.
  • 87.
  • 93.
  • 106.