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
  2. W H Y P H O E N I X

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

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

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

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

    ? Who gives a flying fuck?
  7. 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!”
  8. 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
  9. W H Y P H O E N I X

    ? If the goal is 100ms how much effort is required to reach that goal?
  10. 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
  11. 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
  12. W H Y P H O E N I X

    ? No caching?
  13. 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
  14. W H Y P H O E N I X

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

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

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

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

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

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

    ? http://sorentwo.com/2016/02/02/caching-what-is-it-good-for.html
  21. 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
  22. 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
  23. 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)
  24. W H Y P H O E N I X

    ? Why does this matter?
  25. 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
  26. W H Y P H O E N I X

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

    ? Can Phoenix’s performance benefits free engineers to work on bigger ideas?
  28. W H Y R A I L S ? Build

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

    for developer happiness
  30. W H Y R A I L S ? The

    problem is state
  31. Pipe operator result = "qux" result = baz(result) result =

    bar(result, opts) result = foo(result, a, b, c)
  32. 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
  33. 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)
  34. 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)
  35. Pattern matching def index(conn, %{"q" = query} = params) do

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

    # ... end http://example.com/foo?q=bar def index(conn, %{"q" = query} = params) do # ... end
  37. 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
  38. 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
  39. 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
  40. 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
  41. Rails Generator rails generate model User name:string bio:text Phoenix Generator

    mix phoenix.gen.model User users name:string bio:text
  42. 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
  43. Changed the world by enabling a generation of developers to

    economically build software-centric companies
  44. OTP

  45. 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