https://www.visualstudio.com/en-us/docs/test/performance-testing/_img/performance-testing/ic838830.png

make

Ruby

great again

 

API on Rails
Benchmark
How to speed up

API on Rails
Benchmark
How to speed up

# config/application.rb 

# require "rails"
# Pick the frameworks you want:
require "active_model/railtie"
# require "active_job/railtie"
require "active_record/railtie"
# require "action_controller/railtie"
# require "action_mailer/railtie"
# require "action_view/railtie"
# require "action_cable/engine"
# require "sprockets/railtie"
# require "rails/test_unit/railtie"
rails new awesome_ruby_app --api
class ApplicationController < JSONAPI::ResourceControllerMetal
  include Knock::Authenticable

  before_action :authenticate_user

  def head(type, options = {}) end # ...
end
gem "jsonapi-resources"

Reduce AR models instances

use views in database

Started GET "/mail-logs" for ::1 at 2017-03-17 18:50:46 +0100
Processing by MailLogsController#index as API_JSON
  MailLog Load (0.4ms)  
        SELECT  "mail_logs".* FROM "mail_logs" 
        ORDER BY "mail_logs"."number" 
        DESC LIMIT $1 OFFSET $2  [["LIMIT", 20], ["OFFSET", 0]]
   (0.3ms)  SELECT COUNT(*) FROM "mail_logs"
Completed 200 OK in 7ms (Views: 0.0ms)

API on Rails
Benchmark
How to speed up

Ruby 2.4.0

Rails 5.0.2

Puma 3.8.1

(single process == one core)

Apache Benchmark 2.3

(10000 request burst on index action)

MBP 2015

Requests per second:    250.07 [#/sec] (mean)
Time per request:       3.999 [ms] (mean)
Time per request:       3.999 [ms] (mean, across all concurrent requests)


Percentage of the requests served within a certain time (ms)
  50%      4
  66%      4
  75%      4
  80%      4
  90%      4
  95%      5
  98%      5
  99%      6
 100%     39 (longest request) 

250 req / s

3.999ms / req

API on Rails
Benchmark

How to speed up

Lets rewrite it all with

xyz framework

let use reverse proxy

and rewrite only heavy loaded API end points

Sinja 1.2.5

Sinatra 2.0.0.rc.1

Sequel 4.44.0

(ActiveSupport 5.0.2 -> jsonapi-serializers)

Puma 3.8.1

(single process == one core)

Apache Benchmark 2.3

(10000 request burst on index action)

MBP 2015'

# frozen_string_literal: true
require 'logger'
require 'sinatra'
require 'sequel'
require 'sinatra/jsonapi'

require 'sinja/sequel/helpers'

DB = Sequel.connect('postgres://localhost/cl-api_development')
DB.extension(:freeze_datasets)
DB.extension(:pagination)
DB.optimize_model_load = true

DB.loggers << Logger.new($stderr) if Sinatra::Base.development?

Sequel::Model.plugin :tactical_eager_loading

class MailLog < Sequel::Model
  many_to_one :category
  many_to_one :company
end

class Category < Sequel::Model
  one_to_many :mail_log
end

class Company < Sequel::Model
  one_to_many :mail_log
end

Sequel::Model.finalize_associations
Sequel::Model.freeze

class BaseSerializer
  include JSONAPI::Serializer
end

class MailLogSerializer < BaseSerializer
  attributes :number, :in_or_out, :document_date_on, :received_on, :external_number, :comment, :value_net, :value_vat

  has_one :category
  has_one :company
end

class CategorySerializer < BaseSerializer
  attributes :name

  has_many :mail_logs
end

class CompanySerializer < BaseSerializer
  attributes :name, :icon

  has_many :mail_logs
end

class MailLogs < Sinatra::Application
  register Sinatra::JSONAPI

  resource 'mail-logs' do
    index do
      MailLog.dataset
    end

  end
end

freeze_jsonapi

70 LOC of Ruby

Requests per second:    746.18 [#/sec] (mean)
Time per request:       1.340 [ms] (mean)
Time per request:       1.340 [ms] (mean, across all concurrent requests)
Transfer rate:          2731.85 [Kbytes/sec] received

Percentage of the requests served within a certain time (ms)
  50%      1
  66%      1
  75%      1
  80%      1
  90%      2
  95%      2
  98%      2
  99%      2
 100%      5 (longest request)

746 req / s

2.98x

1.340 ms / req (median)

2.98x

Ruby is

 fast enough

 

make ruby great again

Michał Czyż

 

@cs3b

Thank You!

Made with Slides.com