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

From Ruby to Elixir

From Ruby to Elixir

my talk at Sardines.rb (Lisbon Ruby meetup)

Daniel Serrano

August 13, 2019
Tweet

More Decks by Daniel Serrano

Other Decks in Programming

Transcript

  1. from Ruby to Elixir

    View Slide

  2. • why elixir?
    • historical context
    • quick intro
    • pipe operator
    • pattern-matching
    • processes
    • supervisors
    • phoenix
    • elixir in real life
    outline

    View Slide

  3. • elixir
    • preemptive Erlang VM
    • yielding lightweight processes
    • no locks, no mutexes, etc.
    • ranch, cowboy
    • functional, immutable
    • ruby
    • MRI relies on GIL
    • OS processes, threads
    • locks, mutexes, etc.
    • WEBrick, unicorn, puma,
    passenger, etc.
    • OO, mutable
    why elixir?

    View Slide

  4. historical context
    • Erlang (1986)
    • Ericsson (OSS 1998)
    • Ruby (1995)
    • Rails (2005)
    • F# (2005)
    • Clojure (2007)
    • Devise (2009)
    • Elixir (2009)

    View Slide

  5. quick intro
    • integers
    • 2, 0xcafe, 0b100, 10_000
    • floats
    • 1.0, 3.1415, 6.02e23
    • lists
    • [1, 2, 3], [head|tail]
    • map
    • %{one: “un”, two: “deux”}
    • atom
    • :foo, :[email protected], :elixir
    • tuple
    • {:ok, 11, ‘hi'}
    • keyword list
    • [a: :foo, b: :bar]
    • binary
    • <<104, 101, 108, 108, 111>>,
    “hello”

    View Slide

  6. quick intro
    • functions
    • Enum.map/2, :erlang.localtime/0
    • examples
    • IO.puts(“Hello World”)
    • Map.get(%{one: “un”}, :one)
    • struct(User,
    %{fname: “John”, lname: “Doe”})
    # prints to stdout
    # returns “un”
    # returns a User struct
    # with first name “John”,
    # last name “Doe”

    View Slide

  7. quick intro
    defmodule User do
    defstruct [:fname, :lname]
    def full_name(%User{fname: fname, lame: lname}) do
    “#{fname} #{lname}”
    end
    end
    $> user = %User{fname: “John”, lname: “Doe”}
    $> User.full_name(user)
    “John Doe”

    View Slide

  8. pipe operator |>
    Enum.max(Enum.map(Enum.filter([1, 2, 3, 4, 5], fn x ->
    rem(x, 2) == 0 end), fn x-> x * 2 end))
    • find max of double the values

    View Slide

  9. pipe operator |>
    Enum.max(
    Enum.map(
    Enum.filter(
    [1, 2, 3, 4, 5],
    fn x -> rem(x, 2) == 0 end
    ),
    fn x-> x * 2 end
    )
    )

    View Slide

  10. pipe operator |>
    [1, 2, 3, 4, 5]
    |> Enum.filter(fn x -> rem(x, 2) == 0 end)
    |> Enum.map(fn x -> x * 2 end)
    |> Enum.max()
    # 8

    View Slide

  11. pattern-matching
    def zero?(0), do: true
    def zero?(_), do: false
    zero?(0)
    zero?(3)
    zero?(“hello”)
    # true
    # false
    # false

    View Slide

  12. pattern-matching
    def started_at_text(%Task{started_at: nil}), do: “Not started”
    def started_at_text(%Task{started_at: time} = task) do

    “Started task-#{task.id} @ #{DateTime.to_string(time)}”
    end
    def state(%Task{started_at: nil, closed_at: nil}), do: :waiting
    def state(%Task{started_at: nil}), do: :canceled
    def state(%Task{closed_at: nil}), do: :in_progress

    View Slide

  13. processes
    process A process B

    View Slide

  14. processes
    BEAM

    View Slide

  15. processes
    BEAM
    2000 reductions each
    before yielding
    multiple schedulers
    ~1 per cpu

    View Slide

  16. processes
    BEAM

    View Slide

  17. processes
    BEAM

    View Slide

  18. processes
    BEAM
    eu-west-1 us-east-1

    View Slide

  19. supervisors
    BEAM

    View Slide

  20. supervisors
    BEAM
    error

    View Slide

  21. supervisors
    BEAM
    restart

    View Slide

  22. one_for_one
    restart
    supervisors
    BEAM

    View Slide

  23. one_for_all
    restart
    supervisors
    BEAM

    View Slide

  24. phoenix

    View Slide

  25. phoenix

    View Slide

  26. phoenix
    Ruby Elixir
    Rack Plug
    Rails Phoenix
    ActiveRecord Ecto
    ERB EEx

    View Slide

  27. elixir in real life
    • 1.5 billion page views per month
    • 200.000 concurrent users
    • resource intensive features
    • previously aggressive horizontal scaling
    • now 1/10th servers with low CPU usage

    View Slide

  28. elixir in real life
    • 100.000 concurrent users
    • previously Java
    • now Erlang, Go and Elixir
    • 10.000s to 100.000s users per machine

    View Slide

  29. elixir in real life
    • 11.000.000 concurrent users
    • 2.600.000 concurrent voice users
    • 220 Gbps
    • 120 Mpps

    View Slide

  30. elixir in real life
    • media service handling millions of reqs/day
    • biometrics aggregator service handling
    100.000s connections per day
    • average of 6 Kubernetes pods
    • cpu limits of 600m
    • mem limits of 512Mi

    View Slide

  31. the end
    thank you
    dnlserrano.dev

    View Slide