Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Why Erlang?

Why Erlang?

With web applications today there is an increasing need for systems that can scale up easily and tolerate the network, hardware, and software errors that occur at scale. Building such systems is challenging, if not impossible, to do in many popular programming languages today. Erlang was designed for telephony systems where uptime requirements were law, and as such was designed to solve these challenges. In this talk I will show how Erlang can be used to solve some of the most challenging problems software developers face today. I will introduce concurrency constructs that Erlang provides and show how they can be used to build reliable and scalable applications. This talk will focus mostly on the new concepts introduced by Erlang, but I will also do a few demos and show code samples to illustrate some of the concepts.

Trevor Brown

July 20, 2017

More Decks by Trevor Brown

Other Decks in Programming


  1. Why Erlang?
    Trevor Brown

    View Slide

  2. Trevor Brown
    Sarasota, Florida
    Erlang, Elixir, Ruby, JavaScript
    Software Developer at Voalte

    View Slide

  3. Reliability
    “the quality of being trustworthy or of performing
    consistently well.”
    – Google Dictionary

    Characteristic of good server software

    Something that must be addressed during development

    View Slide

  4. Potential Faults - Hardware

    Hardware faults will be encountered

    Transient faults
    – Loss of power
    – Loss of network connectivity
    – Disk full

    Permanent faults
    – Hard disk failure

    Human error

    View Slide

  5. Potential Faults - Software

    Again, software faults will be encountered

    Unanticipated hardware failures

    Software bugs present in other systems

    Software bugs in your own code

    View Slide

  6. Fault Tolerance

    Reliable software must be able to handle faults in an
    intelligent way
    – Sometimes crashing
    – Sometimes retrying the failed action
    – Ignoring faults is always bad

    Without some sort of fault tolerance larger software
    systems will be brittle, crashing the first time a fault

    View Slide

  7. Most Modern Languages
    Don’t Handle Faults Well

    View Slide

  8. Most Languages

    Weren’t designed with fault tolerance in mind

    Don’t have constructs for dealing with
    unexpected exceptions

    Not suited for long-running server software

    Usually rely on other OS-level tools when faults
    crash the application

    View Slide

  9. Let’s look at how fault tolerance is
    handled in hardware systems...

    View Slide

  10. Data centers have systems in place
    that ensure their servers remain

    View Slide

  11. Data Center Power Supply

    View Slide

  12. Fault tolerance is achieved through
    isolation and redundancy

    View Slide

  13. Fault removal is also necessary for
    long term reliability

    View Slide

  14. Software reliability can be
    achieved the same way

    View Slide

  15. This cannot be done with most
    language runtimes

    View Slide

  16. Language Limitations

    Single thread of execution*

    Code that is executing has full control
    – May crash the process
    – May meddle with any data

    Single thread limits error handling abilities

    View Slide

  17. Error Handling Insufficiencies

    Unhandled exceptions always crash the application
    – Exceptions must be caught if the application is to continue

    Some exceptions cannot reasonably be handled inline
    – Software bugs are a common source of faults and often result
    in exceptions
    – Some potential exceptions are intentionally ignored
    – Impossible to enumerate all potential exceptions

    View Slide

  18. Caused by Lack of Isolation

    Single thread of execution is the biggest weakness
    – Everything is under it’s control
    – No redundancy, we don’t have other threads of execution for backup

    When a function calls another function it is passing it the all
    powerful thread of execution
    – There is no way for the original caller to take back this power
    – Rest of the application is powerless and must wait for the function to
    – No, it’s not sending it a message

    View Slide

  19. How do we solve this?

    View Slide

  20. True Isolation

    Multiple threads of execution

    Each with their own memory

    No shared memory between them

    Preemptive scheduling so CPU time is shared fairly
    among them

    View Slide

  21. Can support for this be added to
    existing languages via libraries?

    View Slide

  22. Limitations of Libraries

    Libraries can't enforce system wide-guarantees
    – Immutable data
    – Memory safety
    – Type safety

    Libraries can't change architecture of the underlying
    – Optimizations
    – Language constructs

    View Slide

  23. A new language is needed when we need to
    enforce additional constraints on our programs
    When features are needed that must be
    provided by the underlying language

    View Slide

  24. Erlang

    View Slide

  25. How does Erlang solve this?

    View Slide

  26. Erlang Processes

    Not correlated with threads or processes
    – Not the same as an OS process

    Each have their own memory
    – Each process is garbage collected individually

    Preemptively scheduled
    – Busy processes won’t hog CPU time

    View Slide

  27. Erlang Processes

    Identified by ID and optionally by name

    Can communicate by placing messages in the mailbox of
    the recipient process

    Can be created on the fly with the spawn command

    Can be monitored by another process so the process can
    take action when the process crashes

    Can be linked to another process so both processes crash
    when an exception occurs

    View Slide

  28. Erlang OTP

    Processes alone aren’t enough
    – Processes only limit the effects of faults
    – Processes cannot restore faulting systems

    OTP is a collection of libraries and tools for building
    systems that can recover from transient faults

    View Slide

  29. Erlang VM



    Mostly functional

    Dynamically typed

    Hot code loading

    View Slide

  30. Language Priorities
    developer friendliness

    View Slide

  31. Erlang Language Constructs

    Spawning processes

    Message passing between processes


    Pattern matching

    View Slide

  32. Processes are Actors

    Ends up feeling like a better OO

    Best implementation of Alan Kay's vision as he described
    it at OOPSLA 1997

    Destroys some OO misconceptions that have been forced
    on us by our languages

    View Slide

  33. Erlang Basics

    View Slide

  34. Data Types

    All data is immutable

    Atoms are just like symbols in Ruby

    No boolean type, just the atoms true and false
    true % No booleans

    View Slide

  35. Binaries and Numbers

    % Binaries
    % Integers
    % Floats

    View Slide

  36. Tuples

    {one, two, three}
    % Tuples are contiguously in memory
    % We can access individual items with element
    element(2, {1,2,3,4}) % => 2

    View Slide

  37. Lists

    No array type, only linked lists.

    Each item contains a pointer to the next them
    Letters = [a,b,c]
    % Items can be added to the front of the
    % list easily
    [d|Letters] % => [d,a,b,c]

    View Slide

  38. Strings (Still Lists)

    No true string type, strings are lists of character codes
    "Joe" % => "Joe" % still just a list
    % $a returns the character code for a
    $a % => 97
    % If lists only contain character codes
    % they will be printed as strings
    [$a, $b, $c] % => "abc"

    View Slide

  39. More Data Types...

    % Maps
    #{key => value}
    % Records
    -record(user, {username, email, password}).
    email="[email protected]"

    View Slide

  40. Modules

    Modules must be defined in a file with the same name
    % Functions must be exported to be used
    % outside module
    % Function here...

    View Slide

  41. Functions

    Functions are identified by name and arity
    % add/2 has two clauses
    add(0, 0) -> 0;
    add(X, Y) -> X + Y.
    % add/3 has one clause
    add(X, Y, Z) -> X + Y + Z.

    View Slide

  42. Pattern Matching

    View Slide

  43. Pattern Matching
    a = a % => a
    a = b % => ** exception error: no match of
    right hand side value b
    Letter = a % => a
    Letter % => a

    View Slide

  44. Pattern Matching Tuples

    {ok, Value} = {ok, "foo bar baz"}
    Value % => "foo bar baz"
    {ok, Value} = {error, crashed}
    % => ** exception error: no match of
    right hand side value crashed

    View Slide

  45. Pattern Matching Lists

    [Head|Tail] = [1,2,3]
    Head % => 1
    Tail % => [2,3]
    [First,Second,Third] = [1,2,3]
    Second % => 2
    [One,Two] = [1,2,3] % ** exception error: no
    match of right hand side value [1,2,3]
    [First,Second|Rest] = [1,2,3]

    View Slide

  46. Underscore Variable

    Can be used in place of a regular variable in a pattern

    No values are bound to it, meaning it can match any
    value anytime it is used

    It’s common to use it if we don’t care about a value in a
    {_, _} = {1,1}
    {_, _} = {1,2}
    {Num, Num} = {1,2} % ** exception error: no
    match of right hand side value {1,2}

    View Slide

  47. Pattern Matching in Functions

    Function clauses use pattern matching to determine
    which clause should be executed
    % add/2 has three clauses
    add(0, 0) -> 0;
    add(X, X) -> X * 2;
    add(X, Y) -> X + Y.

    View Slide

  48. Recursion

    View Slide

  49. Recursion

    Recursive functions are functions that call themselves

    Recursive functions are used when repetition is needed

    If a function calls itself and never returns an infinite loop is

    Tail call and other optimizations so you never run out of
    stack space

    View Slide

  50. Recursion
    sum_list(List) -> sum_list(List, 0).
    sum_list([], Acc) -> Acc;
    sum_list([Head|Tail], Acc) ->
    sum_list(Tail, Acc + Head).

    View Slide

  51. Processes

    View Slide

  52. Process Messaging
    % `Pid` is a process ID
    Pid ! {add, 1, 2, self()}
    % Receive a message in the process
    {add, X, Y, Caller} ->
    % Send the result back
    Caller ! add(X, Y)
    _ ->

    View Slide

  53. Spawning a Process

    Processes will return until the function they are running
    ends or encounters an exception

    Recursive functions are typically used for servers
    % Assuming ?MODULE:math_server/0 is a function
    {ok, Pid} = spawn(?MODULE, math_server, []).

    View Slide

  54. Math Server Demo
    • API for the caller
    • API calls send messages to the server, which does
    the arithmetic
    • Result is sent back to the client process via a
    message, which then causes the original call to return
    with the result
    • With and without OTP supervision

    View Slide

  55. Math Server Demo
    Math Server
    Shell Process (Us)
    {add, 1, 2}
    {response, 3}

    View Slide

  56. Demo

    View Slide

  57. Conclusion

    View Slide

  58. Conclusion

    Fault tolerance is at the center of Erlang’s design

    Erlang gives us the constructs we need to build concurrent

    OTP gives us the tools we need to build fault tolerant
    applications in Erlang

    Erlang’s concurrency model enables Erlang to support things
    like distribution and hot code upgrades

    Erlang is an ideal choice if you want a language that can scale
    with your company

    View Slide

  59. Things I Didn’t Cover

    OTP behaviors


    List comprehensions

    Type checking with Dialyzer

    And much more...

    View Slide

  60. Resources

    Official Website - http://www.erlang.org/

    Online REPL - http://www.tryerlang.org/

    Free Book on Erlang - http://learnyousomeerlang.com/

    Programming Erlang Book -

    View Slide

  61. Trevor Brown
    [email protected]

    View Slide