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!
Choosing Ruby to serve JSONAPI at speed
By Michał Czyż
Choosing Ruby to serve JSONAPI at speed
rails ruby jsonapi-resources puma apache benchmark ab sinja sinatra sequel single process
- 1,383