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

From Rails to Phoenix

From Rails to Phoenix

If you are interested in learning more about how your organization can transition from Rails to Phoenix please contact the Elixir/Phoenix experts at DockYard!

http://dockyard.com

Brian Cardarella

May 08, 2016
Tweet

More Decks by Brian Cardarella

Other Decks in Programming

Transcript

  1. F R O M R A I L S T O
    P H O E N I X
    B R I A N C A R D A R E L L A

    View Slide

  2. W H Y P H O E N I X ?

    View Slide

  3. W H Y P H O E N I X ?
    Performance!

    View Slide

  4. W H Y P H O E N I X ?

    View Slide

  5. W H Y P H O E N I X ?

    View Slide

  6. W H Y P H O E N I X ?

    View Slide

  7. W H Y P H O E N I X ?
    Performance!
    This is the gateway drug for Phoenix

    View Slide

  8. W H Y P H O E N I X ?
    Is Performance Enough?

    View Slide

  9. W H Y P H O E N I X ?
    I see a lot of “Hello World” benchmarks that [respond] in nanoseconds.

    View Slide

  10. W H Y P H O E N I X ?
    Who gives a flying fuck?

    View Slide

  11. W H Y P H O E N I X ?
    Have you ever met a customer who said “Your page
    rendered in 100ms, that is not good enough. I need nanoseconds!”

    View Slide

  12. W H Y P H O E N I X ?
    No one ever asks for that. - DHH
    https://www.youtube.com/watch?v=ktZLpjCanvg&t=9m49s

    View Slide

  13. W H Y P H O E N I X ?
    If the goal is 100ms how much effort
    is required to reach that goal?

    View Slide

  14. W H Y P H O E N I X ?

    View Slide

  15. W H Y P H O E N I X ?
    Eight year old Rails application (~50 models, ~40 controllers)
    Rewrite in Elixir/Phoenix began in 2014
    Before:
    150 AWS Instances
    Log-jammed responses
    Multiple engineers per app
    Multiple complex caching strategies

    View Slide

  16. W H Y P H O E N I X ?
    Eight year old Rails application (~50 models, ~40 controllers)
    Rewrite in Elixir/Phoenix began in 2014
    Results:
    1/15th of the servers previously required
    10ms - 30ms avg response times
    Largest average spike 400ms
    Largest outlier spike 800ms
    About one engineer per app
    No caching

    View Slide

  17. W H Y P H O E N I X ?
    No caching?

    View Slide

  18. W H Y P H O E N I X ?
    What Rails developers are told
    1. Call to the database as little as possible
    2. Render from cache as much as possible

    View Slide

  19. W H Y P H O E N I X ?

    View Slide

  20. W H Y P H O E N I X ?

    View Slide

  21. W H Y P H O E N I X ?

    View Slide

  22. W H Y P H O E N I X ?
    How?

    View Slide

  23. W H Y P H O E N I X ?
    1. Elixir is must at faster garbage collection

    View Slide

  24. W H Y P H O E N I X ?
    2. Elixir consumes all CPU cores

    View Slide

  25. W H Y P H O E N I X ?
    3. Elixir is a compiled language

    View Slide

  26. W H Y P H O E N I X ?
    4. Phoenix makes smart use of the BEAM

    View Slide

  27. W H Y P H O E N I X ?
    http://www.evanmiller.org/elixir-ram-and-the-template-of-doom.html

    View Slide

  28. W H Y P H O E N I X ?
    5. The database is not slow

    View Slide

  29. W H Y P H O E N I X ?

    View Slide

  30. W H Y P H O E N I X ?
    http://sorentwo.com/2016/02/02/caching-what-is-it-good-for.html

    View Slide

  31. W H Y P H O E N I X ?
    Ruby/Rails
    • Ruby 2.3 / Rails 4.2.5.1 with ActiveRecord
    • Fronted by a Redis cache that combines Perforated and Readthis
    • Content serialized with ActiveModelSerializers, unused with a warm cache
    • Tuned to fetch as little data as possible from the database
    • All associations are preloaded
    • All content is cached as strings, no marshalling or serialization is performed
    • All data is generic, not customized to the current user
    • The request is paginated to 100 primary records, without a limit on side loads
    • The payload is a hefty 160k, un-gzipped
    http://sorentwo.com/2016/02/02/caching-what-is-it-good-for.html

    View Slide

  32. W H Y P H O E N I X ?
    Elixir/Phoenix
    • Elixir 1.2.1 / Phoenix 1.1
    • No entity cache
    • All fields are fetched from the database, SELECT *
    • All JSON responses are serialized on the fly, directly in views
    • Includes customized data based on the current user
    • The request isn’t paginated at all, there are 250 primary records
    • The payload is a massive 724k, un-gzipped
    http://sorentwo.com/2016/02/02/caching-what-is-it-good-for.html

    View Slide

  33. W H Y P H O E N I X ?
    “These response times are not characteristic of either system,
    they are at the extreme upper limit. Even so, serving up 2.5x
    the records with 4.5x the data, without any caching, the
    Phoenix API response times are 1.5x-2.5x faster.”
    — Parker Selbert
    http://sorentwo.com/2016/02/02/caching-what-is-it-good-for.html
    Rails
    Phoenix
    response time (ms)

    View Slide

  34. W H Y P H O E N I X ?
    Why does this matter?

    View Slide

  35. W H Y P H O E N I X ?
    Eight year old Rails application (~50 models, ~40 controllers)
    Rewrite in Elixir/Phoenix began in 2014
    Results:
    1/15th of the servers previously required
    10ms - 30ms avg response times
    Largest average spike 400ms
    Largest outlier spike 800ms
    About one engineer per app
    No caching

    View Slide

  36. W H Y P H O E N I X ?
    About one engineer per app

    View Slide

  37. W H Y P H O E N I X ?
    Can Phoenix’s performance benefits free
    engineers to work on bigger ideas?

    View Slide

  38. W H Y P H O E N I X ?

    View Slide

  39. W H Y R A I L S ?

    View Slide

  40. W H Y R A I L S ?
    Build something in half
    the time for half the cost.
    Optimize for developer happiness

    View Slide

  41. W H Y R A I L S ?
    Optimize for developer happiness

    View Slide

  42. W H Y R A I L S ?
    The problem is state

    View Slide

  43. View Slide

  44. Are you really happy working
    with your old code?

    View Slide

  45. Are you really happy working with
    other people’s old code?

    View Slide

  46. View Slide

  47. Math.add(1, 2)

    View Slide

  48. View Slide

  49. Functions are “pure”
    Variables are immutable
    Explicit > Implicit

    View Slide

  50. Simpler system to hold in your head
    Documentation is easier to find
    Code is easier to test

    View Slide

  51. Elixir took the best of other languages

    View Slide

  52. defmodule Person do
    def say(words) do
    IO.puts(words)
    end
    end
    Person.say("Hello world!")
    Syntax (Ruby)

    View Slide

  53. Pipe operator (F#)
    foo(bar(baz("qux"), opts), a, b, c)

    View Slide

  54. Pipe operator
    result = "qux"
    result = baz(result)
    result = bar(result, opts)
    result = foo(result, a, b, c)

    View Slide

  55. Pipe operator
    "qux"
    |> baz()
    |> bar(opts)
    |> foo(a, b, c)

    View Slide

  56. Pattern matching
    def fast_multiply(0, n) do
    0
    end
    def fast_multiply(1, n) do
    n
    end
    def fast_multiply(x, n) do
    x * n
    end

    View Slide

  57. Pattern matching
    def fast_multiply(0, n) do
    0
    end
    def fast_multiply(1, n) do
    n
    end
    def fast_multiply(x, n) do
    x * n
    end
    fast_multiply(0, 5)

    View Slide

  58. Pattern matching
    def fast_multiply(0, n) do
    0
    end
    def fast_multiply(1, n) do
    n
    end
    def fast_multiply(x, n) do
    x * n
    end
    fast_multiply(2, 5)

    View Slide

  59. Pattern matching
    def index(conn, params) do
    # ...
    end

    View Slide

  60. Pattern matching
    def index(conn, %{"q" = query} = params) do
    # ...
    end
    http://example.com/foo?q=bar

    View Slide

  61. Pattern matching
    def index(conn, %{"q" = “bar”} = params) do
    # ...
    end
    http://example.com/foo?q=bar
    def index(conn, %{"q" = query} = params) do
    # ...
    end

    View Slide

  62. Elixir & Phoenix optimize for long-
    term developer happiness

    View Slide

  63. How do Rails developers transition to Phoenix?

    View Slide

  64. rails-app
    !"" Gemfile
    !"" README.md
    !"" app/
    # !"" assets/
    # !"" channels/
    # !"" controllers/
    # !"" helpers/
    # !"" jobs/
    # !"" mailers/
    # !"" models/
    # %"" views/
    !"" config
    # %"" router.rb
    !"" db/
    !"" log/
    !"" public/
    %"" test/
    Rails App Structure
    phoenix_app
    !"" README.md
    !"" config/
    !"" lib/
    !"" mix.exs
    !"" priv/
    !"" test/
    %"" web/
    !"" channels/
    !"" controllers/
    !"" models/
    !"" static/
    !"" templates/
    !"" views/
    !"" router.ex
    %"" web.ex
    Phoenix App Structure

    View Slide

  65. HuhApp::Application.routes.draw do
    resources :profiles, only: [:show]
    get 'profiles/:id/reviews' => 'profiles#reviews'
    end
    Rails Router
    Phoenix Router
    defmodule HuhApp.Router do
    use HuhApp.Web, :router
    resources "/profiles", HuhApp.ProfileController, only: [:show]
    get "/profiles/:id/reviews", HuhApp.ProfileController, :reviews
    end

    View Slide

  66. Rails Controller
    class ProfilesController < ApplicationController
    def show
    @profile = Profile.find(params[:id])
    end
    end
    Phoenix Controller
    defmodule HuhApp.ProfileController do
    def show(conn, %{"id" => id}) do
    profile = Repo.get(Profile, id)
    render conn, "show.html", profile: profile
    end
    end

    View Slide

  67. Rails Migration
    class CreateProfiles < ActiveRecord::Migration
    def change
    create_table :profiles do |t|
    t.string :name
    t.timestamps
    end
    end
    end
    Phoenix (Ecto) Migration
    defmodule HuhApp.Repo.Migrations.CreateProfile do
    use Ecto.Migration
    def change do
    create table(:profiles) do
    add :name, :string
    timestamps
    end
    end
    end

    View Slide

  68. Rails Generator
    rails generate model User name:string bio:text
    Phoenix Generator
    mix phoenix.gen.model User users name:string bio:text

    View Slide

  69. Rake & Bundler
    Mix

    View Slide

  70. irb, ruby-debug, & PRY
    iex, Erlang debugger, & IEx.pry

    View Slide

  71. Technical Requirement Server A Server B
    Http Server Nginx & Phusion Elixir
    Request Processing Ruby On Rails Elixir
    Long Running Requests Go Elixir
    Server-Wide State Redis Elixir
    Persistable Data Redis & Mongo Elixir
    Background Jobs Cron, Bash Scripts & Ruby Elixir
    Service Crash Recovery Upstart Elixir

    View Slide

  72. Phoenix is inspired by Rails

    View Slide

  73. Elixir is inspired by Ruby

    View Slide

  74. Elixir == Ruby for Erlang
    Phoenix == Rails for Elixir

    View Slide

  75. Elixir is not Ruby

    View Slide

  76. Phoenix is not Rails

    View Slide

  77. https://dockyard.com/blog/2015/11/18/phoenix-is-not-rails

    View Slide

  78. Performance is the least interesting
    thing about Phoenix

    View Slide

  79. Changed the world by enabling a
    generation of developers to
    economically build software-centric
    companies

    View Slide

  80. View Slide

  81. View Slide

  82. OTP

    View Slide

  83. Open
    Telecom
    Platform

    View Slide

  84. http://www.phoenixframework.org/blog/the-road-to-2-million-websocket-connections

    View Slide

  85. How do you learn Phoenix?

    View Slide

  86. Pre-existing domain knowledge speeds up adoption

    View Slide

  87. Pre-existing domain knowledge speeds up adoption
    DockYard team one week to transition

    View Slide

  88. Dave Thomas
    Hal Fulton
    Sasa Juric Chris McCord
    Bruce Tate
    Jose Valim

    View Slide

  89. Dave Thomas Hal Fulton

    View Slide

  90. W H Y P H O E N I X ?

    View Slide

  91. W H Y P H O E N I X ?
    Order of magnitude performance
    Avoid having to wrap all code in caches
    Implementing features costs less money and requires
    less engineering support
    Optimizes for long-term developer happiness
    Takes about a week to re-train Rails developers
    Its going to change the world

    View Slide

  92. Brian Cardarella
    @bcardarella
    If you want to build something great with Elixir or
    Phoenix hire @DockYard

    View Slide

  93. Thank You!

    View Slide