Concepts of programming languages - Lecture 9 · 2016-12-22 · FacultyofScience...
Transcript of Concepts of programming languages - Lecture 9 · 2016-12-22 · FacultyofScience...
Faculty of ScienceInformation and Computing Sciences
1
Concepts of programming languagesLecture 9
Wouter Swierstra
Faculty of ScienceInformation and Computing Sciences
2
Last time
▶ How do other (typed) languages support this style ofmetaprogramming?
▶ Case studies: when do people use reflection?▶ Embedding DSLs using quasiquotation.
Faculty of ScienceInformation and Computing Sciences
3
This time
Concurrency and parallelism
▶ Why is this important?▶ What are these two concepts?▶ How does Erlang address these challenges?
Faculty of ScienceInformation and Computing Sciences
4
Modern server software is demanding to develop andoperate: It must be available at all times and in alllocations; it must reply within milliseconds to userrequests; it must respond quickly to capacitydemands; it must process a lot of data and even moretraffic; it must adapt quickly to changing productneeds; and, in many cases, it must accommodate alarge engineering organization, its many engineersthe proverbial cooks in a big, messy kitchen.
Marius Eriksen, Twitter Principle Engineer, Functional atScale, CACM December 2016
Faculty of ScienceInformation and Computing Sciences
5
Concurrency & parallelism
A parallel program is a program that uses multiplicity ofcomputer hardware to perform a computation more quickly
A concurrent program has multiple threads of control.Conceptually, these threads execute ‘at the same’ time,interleaving their effects.
These notions are not the same!
Programs may be both parallel and concurrent, one of thetwo, or neither.
Faculty of ScienceInformation and Computing Sciences
6
Determinism and non-determinism
A program that will return a single result is said to bedeterministic.
When different runs of the programmay yield differentresults, the program is non-deterministic.
Concurrent programs are necessarily non-deterministic –depending on how threads are interleaved, they maycompute different results.
Concurrent and non-deterministic programs are muchharder to test and verify.
Faculty of ScienceInformation and Computing Sciences
7
Why care about concurrency and parallelism?
Computers are not getting much faster: instead they havemore and more cores. To exploit this hardware we needparallelism.
Programs no longer run in isolation. They areinter-connected – to different machines, to users, tosubsystems. To structure such interconnected programs, weneed concurrency.
Faculty of ScienceInformation and Computing Sciences
8
Why concurrency?
First, scale implies concurrency. For example, a searchengine may split its index into many small pieces (orshards) so the entire corpus can fit in main memory.To satisfy queries efficiently, all shards must bequeried concurrently. Second, communicationbetween servers is asynchronous and must behandled concurrently for efficiency and safety.
Marius Eriksen, Twitter Principle Engineer, Functional atScale, CACM December 2016
Faculty of ScienceInformation and Computing Sciences
9
Concurrency models
Traditionally, concurrency is done through spawning orforking new threads.
There are numerous synchronization primitives toco-ordinate between threads: locks, mutexes, semaphores,…
If you’ve taken the course on Concurrency, you will haveseen how to write algorithms using them.
Faculty of ScienceInformation and Computing Sciences
10
Concurrency models
Programming with concurrency is really hard.
In particular, once you have state that ismutable and sharedbetween threads, it becomes almost impossible to reasonabout your program.
How can both threads reach the critical sectionsimultaneously?
Faculty of ScienceInformation and Computing Sciences
11
a=0;
Thread one
a = a + 1;if (a == 1) {
critical_section();}
Thread two
a = a + 1;if (a == 1) {
critical_section();}
Faculty of ScienceInformation and Computing Sciences
12
Atomicity
Assignments are not atomic operations.
Instead they read in the current value of a, increment thatvalue, and store it again.
This can cause all kinds of undesirable interaction!
Check out The Deadlock Empire(https://deadlockempire.github.io/) or our Concurrencycourse.
Programming with locks and threads directly is really hard.
Faculty of ScienceInformation and Computing Sciences
13
—
Faculty of ScienceInformation and Computing Sciences
14
Beyond locks and threads
Locks and threads are at the heart of any concurrentprogram.
More recently, languages have started to offer differentabstractions, often built on top of simple locks and threads:
▶ actor model/message passing▶ software transactional memory▶ exploiting data parallelism▶ executing code on GPUs
These all represent different tools, specifically designed fordifferent problems.
Faculty of ScienceInformation and Computing Sciences
15
Erlang
Originally developed in 1986 at Ericsson, it aimed to improvethe software running on telephony switches.
Specifically designed for concurrent programming withmany different processes that might fail at any time.
Open source release together with OTP (Open TelecomPlatform) containing:
▶ Erlang compiler and interpreter;▶ communication protocol between servers;▶ a static analysis tool (Dialyzer);▶ a distributed database server (Mnesia);▶ …
Faculty of ScienceInformation and Computing Sciences
16
Does anyone use Erlang?
▶ Social media:▶ WhatsApp▶ Grindr
▶ Betting websites▶ William Hill▶ Bet365
▶ Telecoms▶ TMobile▶ AT&T
▶ Much, much more..
Faculty of ScienceInformation and Computing Sciences
16
Does anyone use Erlang?
▶ Social media:▶ WhatsApp▶ Grindr
▶ Betting websites▶ William Hill▶ Bet365
▶ Telecoms▶ TMobile▶ AT&T
▶ Much, much more..
Faculty of ScienceInformation and Computing Sciences
17
Erlang for Haskell programmers
Erlang is:
▶ dynamically typed;▶ strict rather than lazy;▶ impure (there are no restrictions on effects and
assignments);▶ the syntax is familiar, but slightly different.
Faculty of ScienceInformation and Computing Sciences
18
Quicksort
qsort([]) -> [];qsort([X|XS]) ->
qsort([Y || Y <- Xs, Y < X])++ [X]++ qsort([Y || Y <- Xs, Y >= X]).
▶ No ‘equations’ but ‘arrows’ when pattern matching.▶ Clauses are separated with semi-colons; a function
definition is finished with a period.▶ All Erlang variables start with capital letters; names
starting with lower-case letters are atoms.
Faculty of ScienceInformation and Computing Sciences
19
Modules
To compile the code, we need to include some moduleinformation
-module(myModuleName)-compile(export_all)
qsort([]) -> ...
This declares the module myModuleName and exports all itsdeclarations.
Faculty of ScienceInformation and Computing Sciences
20
Hello Erlang!
-module(hello).-export([start/0]).
start() ->io:format("Hello Erlang!").
The export statement can be used to expose certainfunctions: note that each statements records the functionsarity (the number of arguments it expects), but not its type.
We can call the format function from the module io usingio:format.
Faculty of ScienceInformation and Computing Sciences
21
Concurrency
Concurrent Erlang programs are organized into processes, alightweight virtual machine that can communicate withother processes.
There are three important functions to define concurrentprograms:
▶ spawn creates a new process;▶ send sends a message to another process;▶ receive receives a message sent by another process.
Faculty of ScienceInformation and Computing Sciences
22
Case study: a concurrent file server
As a simple example to illustrate this concurrency model,consider defining a simple concurrent file server and itsclient:
▶ the afile_server module waits for messages from theclient;
▶ the afile_client module may send messages to theserver requesting data.
Faculty of ScienceInformation and Computing Sciences
23
Case study: the server
-module(afile_server)-export([start/1,loop/1])
start(Dir) -> spawn(afile_server, loop, [Dir])
loop(Dir) -> ...
Modules and processes are a bit like classes and objects:there may be many processes running code defined in thesame module.
When a new afile_server is started using start, a newprocess is spawned. In this example, the process is spawnedby calling the method loop from the module afile_serverwith the argument [Dir].
Faculty of ScienceInformation and Computing Sciences
24
Case study: the server
loop(Dir) ->receive
{Client, list_dir} ->Client ! {self(), file:list_dir(Dir)};
{Client, {get_file, File}} ->Full = filename:join(Dir,File)Client ! {self(), file:read_file(Full)}
end,loop(Dir).
This code waits for a message from the client (receive …).
Once the message has been received and processed, it callsloop(Dir) again to receive a newmessage, ad infinitum.
Faculty of ScienceInformation and Computing Sciences
25
Case study: the server
receive{Client, list_dir} ->
Client ! {self(), file:list_dir(Dir)};{Client, {get_file, File}} ->
Full = filename:join(Dir,File)Client ! {self(), file:read_file(Full)}
end,
The receive ... end statement pattern matches on themessage it receives from the client.
Note: variables bound are written with capitals; constantsstart with a lower-case letter.
Faculty of ScienceInformation and Computing Sciences
26
Case study: the server
receive{Client, list_dir} ->
Client ! {self(), file:list_dir(Dir)};{Client, {get_file, File}} ->
Full = filename:join(Dir,File)Client ! {self(), file:read_file(Full)}
end,
Here we expect one of two commands:
▶ {Client, list_dir} – the client asks us to list the filesin the directory Dir;
▶ {Client, {get_file, File}} – the client asks us toreturn the contents of the file File.
Faculty of ScienceInformation and Computing Sciences
27
Case study: the server
receive...{Client, {get_file, File}} ->
Full = filename:join(Dir,File)Client ! {self(), file:read_file(Full)}
If we receive the {get_file, File} message from theclient Client: * compute the absolute file name. * send anewmessage to the client with the file contents. * thesender of this message is self()
All messages are tagged with their sender.
(The notation {X,Y} creates a tuple in Erlang.)
Faculty of ScienceInformation and Computing Sciences
28
Case study: the client
-module(afile_client).-export([ls/1,get_file/2]).
ls(Server) ->Server ! {self(), list_dir},receive
{Server, FileList} -> FileListend.
get_file(Server, File) ->Server ! {self(), {get_file, File}},receive
{Server, Content} -> Contentend.
Faculty of ScienceInformation and Computing Sciences
29
Case study: the client
This example shows that there is symmetry between theclient and server.
Whenever one sends a message, the other is expecting oneand visa versa.
Our code is structured in different modules, each which maycorrespond to one or more processes at run-time.
These processes communicate throughmessage passing.
Faculty of ScienceInformation and Computing Sciences
30
Connecting the two
We can test our server in isolation by sending it messagesfrom the REPL.
Or start a server and a client and connect the two:
> c(afile_server).{ok,afile_server}> c(afile_client).{ok,afile_client}> FileServer = afile_server:start(".").<0.43.0>> afile_client:get_file(FileServer,"missingfile").{error,enoent}> afile_client:get_file(FileServer,"hello.txt").{ok, <<"hello there...}
Faculty of ScienceInformation and Computing Sciences
31
Data types
Erlang lets you define algebraic data types and declare typesfor your functions:
-spec plan_route(point(), point()) -> route().-type direction() :: north | east | south | west.-type point() :: {integer(),integer()}.-type route() :: [{go,direction(),integer()}.
The Erlang Dialyzer is a static-analysis tool that tries todetect whether or not a program will crash.
Faculty of ScienceInformation and Computing Sciences
32
The Dialyzer
When the Erlang Dialyzer warns your program will fail, youcan be sure that it will fail (soundness).
If the Dialyzer does not warn that your program will fail, youcannot be sure that it will not fail (completeness).
It works even if you do not provide type annotations (typeinference), and uses what Erlang calls success typing – assumeeverything will work out, but raise a warning if it cannot.
Faculty of ScienceInformation and Computing Sciences
33
Pattern matching
Note that pattern matching may be contain more than oneoccurence of the same variable:
eq(X,X) -> "The arguments are equal";eq(X,Y) -> "The arguments are different".
Erlang is dynamically typed: you can tag tuples with an atomrather than introduce a algebraic data type if you wish.
Faculty of ScienceInformation and Computing Sciences
34
Error handling
Many languages encourage defensive programming – checkall possible ways a function can fail.
In Erlang, this idea is built into the language: when you call afunction in an invalid way, it will crash.
But it is also part of the Erlang philosophy: Let it crash!
▶ exit(Why) terminate current process (and notify anyconnected processes that this process has terminated)
▶ throw(Why) throw an exception that the caller maywant to catch.
▶ error(Why) crash unexpectedly
Faculty of ScienceInformation and Computing Sciences
35
Erlang philosophy: let it crash!
Never return a bogus value (like other languages such asJavascript).
Fail fast and noisily and let the caller handle the error, usinga try-catch block:
try FunctionOrExpression ofPattern1 -> Expression1;Pattern2 -> Expression2;...
catchExceptionType1: ExPattern1 -> ExExpression1;...
afterAfterExpressions
end.
Faculty of ScienceInformation and Computing Sciences
36
Erlang design principles
▶ Everything is a process.▶ Processes are strongly isolated – they do not share
memory.▶ Process creation and destruction is a lightweight
operation.▶ Message passing is the only way for processes to
interact.▶ Processes have unique names.▶ If you know the name of a process you can send it a
message.▶ Processes share no resources.▶ Error handling is non-local.▶ Processes do what they are supposed to do or fail.
Faculty of ScienceInformation and Computing Sciences
37
Erlang philosophy: concurrency everywhere
Object oriented programmers try to model the world usingclasses and objects.
Erlang takes a similar ‘philosophical position’: everything is aprocess; processes communicate through message passing.
When a process fails, all connected processes are notified.
Faculty of ScienceInformation and Computing Sciences
38
Erlang processes
Note: Erlang processes are not operating system processes.They are small, self-contained virtual machines runningErlang code.
These processes are created (spawn) and can send (Pid !Message) and receive (receive ... end) messages.
Processes all have an associated ‘mailbox’ – even when theyare not waiting to receive a message, incoming messageswill be stored.
Faculty of ScienceInformation and Computing Sciences
39
Processes vs functions
It’s trivial to turn any function into a ‘server’ handling thatfunction:
area({rectangle, Width, Height}) -> Width * Height;area({square, Side}) -> Side * Side.
Versus
loop() ->receive
{rectangle, Width,Height} ->io:format("Area is~p~n", [Width * Height])loop();
...
Faculty of ScienceInformation and Computing Sciences
40
Organizing processes
The lightweight nature of creating new processes raises newa design question: How do we organize our code intoprocesses? Which processes communicate? And whatmessages do they send one another?
Client-server
Two processes:
▶ the client sends requests to the server;▶ the server computes a suitable reply and sends a
response to the client.
We saw this already in the file server example.
Faculty of ScienceInformation and Computing Sciences
40
Organizing processes
The lightweight nature of creating new processes raises newa design question: How do we organize our code intoprocesses? Which processes communicate? And whatmessages do they send one another?
Client-server
Two processes:
▶ the client sends requests to the server;▶ the server computes a suitable reply and sends a
response to the client.
We saw this already in the file server example.
Faculty of ScienceInformation and Computing Sciences
41
Client server
Instead of tagging all messages with process ids explicitly,we can define an auxiliary function rpc (remote procedurecall):
rpc(Pid,Request) ->Pid ! {self(), Request},receive
Response ->Response
end
This tags every request with the Pid to which to respond.
Faculty of ScienceInformation and Computing Sciences
42
Updating the loop function
The branches of our loop function send messages, insteadof printing to the terminal:
{From, {rectangle, Width, Height}} ->From ! Width * Height,loop();
Faculty of ScienceInformation and Computing Sciences
43
But…
▶ If we receive an unexpected message, we’ll get andynamic pattern match failure.
▶ The rpc function sends a request to the server andawaits a response. If some other process sends amessage before the server responds, we may return anincorrect result.
▶ We need to explicitly spawn the server when we wantto start it up.
Faculty of ScienceInformation and Computing Sciences
44
Receiving unexpected message types
To handle unexpected messages, we can simply send anerror back to the sender.
We add a third branch to the loop function:
{From, Other} ->From ! {error, Other},loop()
Faculty of ScienceInformation and Computing Sciences
45
Receiving messages from unexpected processes
We need to ensure that the response we get in the rpcfunction is really from the process we’re expecting:
rpc(Pid, Request) ->Pid ! {self(), Request),receive
{Pid, Response} ->Response
end.
The Pid in the receive clause is no longer a bindingoccurrence! It must be equal to the Pid function argument.
Any messages from a different Pid are queued.
Faculty of ScienceInformation and Computing Sciences
46
Creating a server
By adding start and area methods, we can make theinteraction with the server a bit easier:
start() -> spawn(area_server, loop, [])
area(Pid,What) ->rpc(Pid, What).
> Pid = area_server:start()<0.36.0>> area_server:area(Pid, {rectangle, 10, 8}).80
Faculty of ScienceInformation and Computing Sciences
47
Processes features
▶ Creating Erlang processes is very cheap – in contrast tocreating new OS processes!
▶ We can add an after clause to a receive statement totimeout after 10 milliseconds:
receive... -> ...
after 10 ->...timeout code...
Faculty of ScienceInformation and Computing Sciences
48
Receiving messages
1. When entering a receive statement, we start a timer;2. Match the first message in the mailbox, with the
patterns one by one. Enter the branch corresponding tothe first match.
3. If no branch matches, add the message to the ‘savequeue’. Try the next message until one does match.
4. If no message matches, suspend the process until a newmessage arrives.
5. If a new message matches, reset the timer and add thesaved messages to the mailbox in the order that theyarrived.
6. If the timer elapses before a message is matched,execute the corresponding timeout expression andrestore the messages in the mailbox.
Faculty of ScienceInformation and Computing Sciences
49
Error handling
In a single threaded program, crashing is bad.
In a concurrent program, if a single process crashes, it is notthe end of our program.
Instead of avoiding crashes, Erlang embraces the fact thatany single process may crash.
The question is: how do we detect crashes and restorecrashed processes?
The focus is on cure rather than prevention.
Faculty of ScienceInformation and Computing Sciences
50
Two slogans
Let some other process fix it
Processes are arranged tomonitor one another for health.When a process crashes, the observing process is informedand takes restorative action.
Let it crash
If necessary, let any individual process crash.
Faculty of ScienceInformation and Computing Sciences
51
Let it crash
▶ No need for checking arguments – just crash▶ No need to perform additional calculations after things
have gone wrong.▶ Clean separation of concerns: other processes handle
the crash; this process does computation only.▶ Crashing early makes it easier to diagnose what wentwrong.
▶ …
Faculty of ScienceInformation and Computing Sciences
52
Erlang: recap
Erlang is a ‘concurrency oriented language’.
Processes are (almost) as easy to work with as functions.
Processes communicate through message passing, but donot share state.
Processes are free to fail; other processes will clean up themess.
Processes can be run on a single machine, or distributedover many different machines.
Faculty of ScienceInformation and Computing Sciences
53
Coming up
▶ Parallel programming with Erlang▶ Concurrent and parallel programming with Haskell
Don’t forget: intermediate project reports due afterChristmas
Faculty of ScienceInformation and Computing Sciences
54
Student assistants wanted!
Looking for active involvement in our teaching?
▶ Apply for a Teaching Assistantship!▶ For period 3 and/or 4▶ 383 ~ 446 euro per month (before tax)▶ 8 hours a week (4 contact hours @UU, 4 @home)▶ Use the form at:
https://wwwsec.cs.uu.nl/education/sollicitatie.php
▶ Deadline: January 9, 2017
Faculty of ScienceInformation and Computing Sciences
55
Sources
▶ Joe Armstrong’s Programming Erlang▶ Simon Marlow’s Parallel and Concurrent Programming in
Haskell