Elixir Processes :
The basic unit of Erlang concurrency model is processes.
In Elixir all code runs inside processes.Processes are isolated from each other, run concurrent to one another and communicate via message passing.Processes also provide means for building distributed and fault tolerant programs.
Elixir processes should not be confused with operating system process.Processes in Elixir are extremely lightweight in terms of memory and CPU(unlike threads in other languages).Hence it is common to handle hundreds and even hundreds of thousands processes simultaneously.
Where do we need process?
Suppose if a client sends a request to server, the server responds with a response.What if the server gets 5 request from different clients at a same time.Or what if a particular client request takes a long time.
Lets take the below ex:
defmodule ProcessEx do
def hello do
IO.puts "Hey I am Done!"
end
end
iex(13)> ProcessEx.hello
Hey I am Done!
:ok
So when you request hello function you will receive the output in a second.
What if you request a function which takes a lot of time to send response.See the below ex:
defmodule ProcessEx do
def hello do
IO.puts "Hey I am Done!"
end
def lazy_process(time) do
time
|> String.to_integer
|> :timer.sleep
hello()
end
end
iex(16)> ProcessEx.lazy_process("10000")
Hey I am Done!
:ok
The lazy_process function takes 10 seconds to finish.So when a server gets a multiple client request at a same time.Server process one request one request at a time.Then obviously the web server becomes slow in giving response.
defmodule ProcessEx do
def hello do
IO.puts "Hey I am Done!"
end
def lazy_process(time) do
time
|> String.to_integer
|> :timer.sleep
hello()
end
end
iex(1)> ProcessEx.lazy_process("10000")
Hey I am Done!
:ok
iex(2)> ProcessEx.hello
Hey I am Done!
:ok
In the above ex if client 1 request lazy_process fn and client 2 request hello fn.Then obviously the client 2 has to wait for 10 seconds until the client 1 lazy_process gets finished.
Solution : Processes
The easiest way to create a new processes is using spawn which takes either anonymous or named function.When we create a new processes, it returns a processes identifier or PID, to uniquely identify it within our application
Spawn will run asynchronously in the background
A basic usage of spawn fn given below
iex(1)> spawn(fn -> IO.puts"Hey Hello" end)
Hey Hello
defmodule ProcessEx do
def hello do
IO.puts "Hey I am Done!"
end
def lazy_process(time) do
IO.puts "I am a lazy process"
time
|> String.to_integer
|> :timer.sleep
hello()
end
def ordinary_process do
lazy_process("10000")
hello()
end
def spawn_process do
spawn(fn -> lazy_process("10000") end)
spawn(fn -> hello() end)
end
end
iex(1)> ProcessEx.ordinary_process()
I am a lazy process
Hey I am Done!
Hey I am Done!
:ok
iex(2)> ProcessEx.spawn_process()
I am a lazy process
Hey I am Done!
Hey I am Done!
You can see the difference between ordinary process and spawn process by running the above code.
Sending and Receiving Messages between Process:
Suppose if there are two processes are running.
For example process 1 and process 2
Now we need the output of process 2 in process 1.How can we achieve this.
Well there is a way, processes will communicate through messages.
lets take an example.iex itself is running in a isolated processess
iex(1)> self()
iex(2)> parent = self()
iex(3)> spawn(fn -> send(parent, {:result, "Process2 message"}) end)
iex(4)> Process.info(parent, :messages)
{:messages, [result: "Process2 message"]}
iex(5)> receive do
...(5)> {:result, mess} -> mess
...(5)> end
iex(6)> Process.info(parent, :messages)
{:messages, []}
If you see the above ex we are storing the iex process id in a variable called parent.
Next we are starting the process 2 using the spawn fn.We get its process Id which is
89.
In that spawn fn(process 2) we are sending the message to process 1.
iex(3)> spawn(fn -> send(parent, {:result, "Process2 message"}) end)
We are checking the process 1 mailbox if it has any messages
iex(4)> Process.info(parent, :messages)
{:messages, [result: "Process2 message"]}
Then we receive the message using the receive function
iex(5)> receive do
...(5)> {:result, mess} -> mess
...(5)> end
we need to match inside the receive fn to match the message.For ex
To match this
{:result, "Process2 message"}
we use this
{:result, mess}
Comments
Post a Comment