Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

pp self •name: Akira Matsuda •from: Tokyo, Japan •GitHub: amatsuda •Twitter: @a_matsuda https://www.flickr.com/photos/mobyrock/308887106/

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

begin

Slide 7

Slide 7 text

Is Rails slow?

Slide 8

Slide 8 text

You may have heard a rumor that...

Slide 9

Slide 9 text

Rails is slow. https://www.flickr.com/photos/naturald/429267360

Slide 10

Slide 10 text

Really? Do you think it's true?

Slide 11

Slide 11 text

If so, •where is it slow? •how is it slow? •why is it slow?

Slide 12

Slide 12 text

Let's benchmark!

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

'JHIUʂ Sinatra

Slide 15

Slide 15 text

Round 1

Slide 16

Slide 16 text

A very simple hello app

Slide 17

Slide 17 text

rails new % rails new rails_israel

Slide 18

Slide 18 text

config/secret.yml production: secret_key_base: something

Slide 19

Slide 19 text

generate controller % rails g controller hello index

Slide 20

Slide 20 text

app/controllers/ hello_controller.rb class HelloController < ApplicationController def index + render text: 'Hello, Israel!' end end

Slide 21

Slide 21 text

rails server % rails s -e production

Slide 22

Slide 22 text

How can we measure?

Slide 23

Slide 23 text

How can we measure? •Let's do it simple.

Slide 24

Slide 24 text

Requesting from the browser

Slide 25

Slide 25 text

The rule •Request 5 times and take the average

Slide 26

Slide 26 text

Results: Rails hello •10ms •9ms •8ms •9ms •9ms •=> 9.0ms

Slide 27

Slide 27 text

Gemfile source 'https://rubygems.org/' gem 'sinatra'

Slide 28

Slide 28 text

Hello from Sinatra require 'bundler/setup' Bundler.require get '/hello' do 'Hello, Israel!' end

Slide 29

Slide 29 text

Starting up Sinatra % RACK_ENV=production bundle ex ruby app.rb

Slide 30

Slide 30 text

Sinatra •9ms •8ms •8ms •7ms •8ms •=> 8.0ms

Slide 31

Slide 31 text

Fact •Rails is 1ms slower than Sinatra.

Slide 32

Slide 32 text

Full-stack vs Micro A micro-framework + 1ms = A full-stack framework

Slide 33

Slide 33 text

In Rails production.log

Slide 34

Slide 34 text

log/production.log I, [2014-11-02T00:06:33.728902 #54125] INFO -- : Started GET "/hello" for ::1 at 2014-11-02 00:06:33 +0900 I, [2014-11-02T00:06:33.729765 #54125] INFO -- : Processing by HelloController#index as HTML I, [2014-11-02T00:06:33.730733 #54125] INFO -- : Rendered text template (0.0ms) I, [2014-11-02T00:06:33.730917 #54125] INFO -- : Completed 200 OK in 1ms (Views: 0.3ms | ActiveRecord: 0.0ms) I, [2014-11-02T00:06:35.626889 #54125] INFO -- : Started GET "/hello" for ::1 at 2014-11-02 00:06:35 +0900 I, [2014-11-02T00:06:35.627652 #54125] INFO -- : Processing by HelloController#index as HTML I, [2014-11-02T00:06:35.628726 #54125] INFO -- : Rendered text template (0.0ms) I, [2014-11-02T00:06:35.628968 #54125] INFO -- : Completed 200 OK in 1ms (Views: 0.4ms | ActiveRecord: 0.0ms) I, [2014-11-02T00:06:37.267414 #54125] INFO -- : Started GET "/hello" for ::1 at 2014-11-02 00:06:37 +0900 I, [2014-11-02T00:06:37.268206 #54125] INFO -- : Processing by HelloController#index as HTML I, [2014-11-02T00:06:37.269261 #54125] INFO -- : Rendered text template (0.0ms) I, [2014-11-02T00:06:37.269509 #54125] INFO -- : Completed 200 OK in 1ms (Views: 0.3ms | ActiveRecord: 0.0ms) I, [2014-11-02T00:06:38.952585 #54125] INFO -- : Started GET "/hello" for ::1 at 2014-11-02 00:06:38 +0900 I, [2014-11-02T00:06:38.953367 #54125] INFO -- : Processing by HelloController#index as HTML I, [2014-11-02T00:06:38.954396 #54125] INFO -- : Rendered text template (0.0ms) I, [2014-11-02T00:06:38.954621 #54125] INFO -- : Completed 200 OK in 1ms (Views: 0.3ms | ActiveRecord: 0.0ms) I, [2014-11-02T00:06:40.761535 #54125] INFO -- : Started GET "/hello" for ::1 at 2014-11-02 00:06:40 +0900 I, [2014-11-02T00:06:40.762368 #54125] INFO -- : Processing by HelloController#index as HTML I, [2014-11-02T00:06:40.763489 #54125] INFO -- : Rendered text template (0.0ms) I, [2014-11-02T00:06:40.763722 #54125] INFO -- : Completed 200 OK in 1ms (Views: 0.4ms | ActiveRecord: 0.0ms)

Slide 35

Slide 35 text

log/production.log I, [2014-11-02T00:06:33.728902 #54125] INFO -- : Started GET "/hello" for ::1 at 2014-11-02 00:06:33 +0900 I, [2014-11-02T00:06:33.729765 #54125] INFO -- : Processing by HelloController#index as HTML I, [2014-11-02T00:06:33.730733 #54125] INFO -- : Rendered text template (0.0ms) I, [2014-11-02T00:06:33.730917 #54125] INFO -- : Completed 200 OK in 1ms (Views: 0.3ms | ActiveRecord: 0.0ms) I, [2014-11-02T00:06:35.626889 #54125] INFO -- : Started GET "/hello" for ::1 at 2014-11-02 00:06:35 +0900 I, [2014-11-02T00:06:35.627652 #54125] INFO -- : Processing by HelloController#index as HTML I, [2014-11-02T00:06:35.628726 #54125] INFO -- : Rendered text template (0.0ms) I, [2014-11-02T00:06:35.628968 #54125] INFO -- : Completed 200 OK in 1ms (Views: 0.4ms | ActiveRecord: 0.0ms) I, [2014-11-02T00:06:37.267414 #54125] INFO -- : Started GET "/hello" for ::1 at 2014-11-02 00:06:37 +0900 I, [2014-11-02T00:06:37.268206 #54125] INFO -- : Processing by HelloController#index as HTML I, [2014-11-02T00:06:37.269261 #54125] INFO -- : Rendered text template (0.0ms) I, [2014-11-02T00:06:37.269509 #54125] INFO -- : Completed 200 OK in 1ms (Views: 0.3ms | ActiveRecord: 0.0ms) I, [2014-11-02T00:06:38.952585 #54125] INFO -- : Started GET "/hello" for ::1 at 2014-11-02 00:06:38 +0900 I, [2014-11-02T00:06:38.953367 #54125] INFO -- : Processing by HelloController#index as HTML I, [2014-11-02T00:06:38.954396 #54125] INFO -- : Rendered text template (0.0ms) I, [2014-11-02T00:06:38.954621 #54125] INFO -- : Completed 200 OK in 1ms (Views: 0.3ms | ActiveRecord: 0.0ms) I, [2014-11-02T00:06:40.761535 #54125] INFO -- : Started GET "/hello" for ::1 at 2014-11-02 00:06:40 +0900 I, [2014-11-02T00:06:40.762368 #54125] INFO -- : Processing by HelloController#index as HTML I, [2014-11-02T00:06:40.763489 #54125] INFO -- : Rendered text template (0.0ms) I, [2014-11-02T00:06:40.763722 #54125] INFO -- : Completed 200 OK in 1ms (Views: 0.4ms | ActiveRecord: 0.0ms)

Slide 36

Slide 36 text

Only 1ms in the Rails land • 1ms (Views: 0.3ms | ActiveRecord: 0.0ms)

Slide 37

Slide 37 text

Acceptable?

Slide 38

Slide 38 text

Acceptable? •To me, yes.

Slide 39

Slide 39 text

Conclusion

Slide 40

Slide 40 text

Conclusion "Rails is NOT slow."

Slide 41

Slide 41 text

end

Slide 42

Slide 42 text

No content

Slide 43

Slide 43 text

Actually,

Slide 44

Slide 44 text

I have 30 minutes today.

Slide 45

Slide 45 text

I have 30 minutes today. •I think I still have time to do one more benchmarking.

Slide 46

Slide 46 text

So, let's benchmark a little bit more realworld-ish app

Slide 47

Slide 47 text

Round 2

Slide 48

Slide 48 text

A scaffold app

Slide 49

Slide 49 text

The Rails scaffold •What we need to do rst before running the scaffold is...

Slide 50

Slide 50 text

To bundle haml •Of course everyone loves Haml, right?

Slide 51

Slide 51 text

Gemfile +gem 'haml-rails'

Slide 52

Slide 52 text

generate scaffold % rails g scaffold user name account email phone zip address birthday:datetime age:integer company bio:text admin:boolean % RAILS_ENV=production rake db:migrate

Slide 53

Slide 53 text

Preparing 10,000 records •Via seeds

Slide 54

Slide 54 text

seeds date_range = Date.parse('1960/1/1').. (10000.days.since(Date.parse('1960/1/1'))) [*1..10000].each do |i| User.create! name: "User %05d" % i, account: "user_%05d" % i, email: "user%05d@example.com" % i, phone: "%011d" % i, zip: "%03d" % (i / 10), address: "#{i}-#{i} Tokyo, Japan" % i, birthday: rand(date_range), age: i / 365, company: "#{i} Signals", bio: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exerci tation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proiden t, sunt in culpa qui officia deserunt mollit anim id est laborum.', admin: true end

Slide 55

Slide 55 text

seeds % RAILS_ENV=production rake db:seed

Slide 56

Slide 56 text

Let's startup the server •And tail the log le

Slide 57

Slide 57 text

% tail -f log/production.log | grep Completed • 4378ms (Views: 4297.7ms | ActiveRecord: 71.5ms) • 4548ms (Views: 4492.5ms | ActiveRecord: 55.0ms) • 4768ms (Views: 4686.3ms | ActiveRecord: 81.2ms) • 4708ms (Views: 4629.7ms | ActiveRecord: 77.7ms) • 4625ms (Views: 4566.1ms | ActiveRecord: 58.3ms)

Slide 58

Slide 58 text

But it causes some errors concerning the assets

Slide 59

Slide 59 text

Getting rid of the layout and assets class UsersController < ApplicationController before_action :set_user, only: [:show, :edit, :update, :destroy] + layout :false ...

Slide 60

Slide 60 text

Without layout • 4807ms (Views: 4730.6ms | ActiveRecord: 75.4ms) • 4712ms (Views: 4638.6ms | ActiveRecord: 72.8ms) • 4453ms (Views: 4378.3ms | ActiveRecord: 74.2ms) • 4665ms (Views: 4575.6ms | ActiveRecord: 88.5ms) • 4785ms (Views: 4691.0ms | ActiveRecord: 93.1ms)

Slide 61

Slide 61 text

No big difference

Slide 62

Slide 62 text

Takes so much time for rendering the view (?) •@users.each is called in the view •So the query execution time was included in the view rendering time

Slide 63

Slide 63 text

to_a the relation in the controller def index - @users = User.all + @users = User.all.to_a end

Slide 64

Slide 64 text

to_a in the controller • 4513ms (Views: 4280.1ms | ActiveRecord: 82.9ms) • 5050ms (Views: 4808.8ms | ActiveRecord: 84.6ms) • 4668ms (Views: 4416.8ms | ActiveRecord: 88.7ms) • 4405ms (Views: 4169.9ms | ActiveRecord: 79.0ms) • 4419ms (Views: 4183.9ms | ActiveRecord: 81.6ms)

Slide 65

Slide 65 text

Rails •4.4ʙ 5.0 seconds •In this case, 98% is consumed in Haml

Slide 66

Slide 66 text

Sinatra's turn

Slide 67

Slide 67 text

Enabling AR and Haml

Slide 68

Slide 68 text

Gemfile gem 'sinatra' +gem 'sinatra-activerecord' +gem 'sqlite3' +gem 'haml'

Slide 69

Slide 69 text

Connecting to DB +set :database, {adapter: 'sqlite3', database: 'production.sqlite3'} +class User < ActiveRecord::Base; end

Slide 70

Slide 70 text

Implementing /users + +get '/users' do + @users = User.all.to_a + haml :index +end

Slide 71

Slide 71 text

Copying files from the Rails app % cp RAILS_APP/db/ production.sqlite3 SINATRA_APP/ % cp RAILS_APP/app/views/users/ index.html.haml SINATRA_APP/views/ index.haml

Slide 72

Slide 72 text

Result NoMethodError - unde ned method `link_to' for #:

Slide 73

Slide 73 text

Getting rid of url helpers •link_to •edit_user_path •new_user_path

Slide 74

Slide 74 text

views/index.haml %td= user.company %td= user.bio %td= user.admin - %td= link_to 'Show', user - %td= link_to 'Edit', edit_user_path(user) - %td= link_to 'Destroy', user, :method => :delete, :data => { :confirm => 'Are you sure?' } - -%br - -= link_to 'New User', new_user_path

Slide 75

Slide 75 text

Result D, [2014-11-03T17:14:49.041718 #36502] DEBUG -- : User Load (52.4ms) SELECT "users".* FROM "users" ::1 - - [03/Nov/2014 17:14:49] "GET /users HTTP/1.1" 200 7318342 0.9010 localhost - - [03/Nov/2014:17:14:48 JST] "GET /users HTTP/1.1" 200 7318342 - -> /users D, [2014-11-03T17:15:15.876042 #36502] DEBUG -- : User Load (54.9ms) SELECT "users".* FROM "users" ::1 - - [03/Nov/2014 17:15:16] "GET /users HTTP/1.1" 200 7318342 0.8763 localhost - - [03/Nov/2014:17:15:15 JST] "GET /users HTTP/1.1" 200 7318342 - -> /users D, [2014-11-03T17:15:18.832111 #36502] DEBUG -- : User Load (51.4ms) SELECT "users".* FROM "users" ::1 - - [03/Nov/2014 17:15:19] "GET /users HTTP/1.1" 200 7318342 1.0335 localhost - - [03/Nov/2014:17:15:18 JST] "GET /users HTTP/1.1" 200 7318342

Slide 76

Slide 76 text

Sinatra •0.9068s •0.9104s •1.0093s •0.9260s •0.9444s

Slide 77

Slide 77 text

Sinatra •0.9 ʙ 1.0 second

Slide 78

Slide 78 text

Rails •4.4ʙ 5.0 seconds

Slide 79

Slide 79 text

OMG! Sinatra is so fast! •Awesome work, Konstantin!

Slide 80

Slide 80 text

But, wait •The templates were little bit different

Slide 81

Slide 81 text

Copying the modified template back to the Rails version % cp SINATRA_APP/views/index.haml RAILS_APP/app/views/users/ index.html.haml

Slide 82

Slide 82 text

Rails without the links • 1642ms (Views: 1411.0ms | ActiveRecord: 73.6ms) • 1712ms (Views: 1500.6ms | ActiveRecord: 59.8ms) • 1644ms (Views: 1432.0ms | ActiveRecord: 55.6ms) • 1751ms (Views: 1503.9ms | ActiveRecord: 72.1ms) • 1741ms (Views: 1465.9ms | ActiveRecord: 83.0ms)

Slide 83

Slide 83 text

Rails without the links •1.6 ʙ 1.8 seconds •Used to be 4.4ʙ 5.0 seconds with the links

Slide 84

Slide 84 text

Fact •60%ʙ 70% of the response time was consumed for drawing links!

Slide 85

Slide 85 text

It's getting closer to Sinatra speed •But still a little bit slow

Slide 86

Slide 86 text

How can we make it faster?

Slide 87

Slide 87 text

GC

Slide 88

Slide 88 text

I heard Ruby GC is slow •Is the GC happening here? •How does it impact the performance?

Slide 89

Slide 89 text

Inspecting the GC •gc_tracer gem by @ko1 • https://github.com/ko1/gc_tracer •Just bundle the gem, and...

Slide 90

Slide 90 text

Tracing the AR query and the view rendering def index - @users = User.all.to_a + GC::Tracer.start_logging(Rails.root.join('tmp/gc.txt').to_s) do + @users = User.all.to_a + render + end end

Slide 91

Slide 91 text

You'll get an output like this each time when GC happens • 550643500349 gc_end_s 56 2734 2734 0 1114375 0 0 457777 2734 0 8743696 7629321 6319200 27416576 40 16 10739 9754 641697 1017174 10477472 21452666 0 newobj 0 0 8971240 528767 230092800 0 0 0 65924 3 0 1 10 186 47 5 1317 625 • 550643568591 gc_start 57 2734 2734 0 1114375 0 0 457777 2734 0 8743696 7629321 6319200 27416576 40 16 10739 9754 641697 1017174 10477472 21452666 shady newobj 0 0 8971257 528772 230092800 0 0 0 65924 3 0 1 10 186 47 5 1317 625 • 550867572379 gc_end_m 57 2734 2734 0 1114375 0 0 457777 2734 0 8743696 7629321 6319200 27416576 40 17 13485 9754 664601 1017174 10477472 21452666 shady newobj 0 0 9057429 528841 230092800 0 0 0 65924 3 0 1 10 186 47 5 1317 634

Slide 92

Slide 92 text

What if we totally stop the GC

Slide 93

Slide 93 text

GC.disable •Add GC.disable to somewhere in the con g le

Slide 94

Slide 94 text

The gc_tracer outputs nothing (but headers) now •Which means that the GC was not executed

Slide 95

Slide 95 text

Results(GC.disable) • 1524ms (Views: 1319.9ms | ActiveRecord: 60.4ms) • 1568ms (Views: 1363.6ms | ActiveRecord: 58.8ms) • 1547ms (Views: 1342.0ms | ActiveRecord: 60.9ms) • 1597ms (Views: 1389.1ms | ActiveRecord: 62.0ms) • 1650ms (Views: 1437.1ms | ActiveRecord: 66.5ms)

Slide 96

Slide 96 text

Fact •Disabling Ruby GC improves the Rails app performance about 10% •The GC overhead used to be like 30% •It's really getting better recently

Slide 97

Slide 97 text

Recent GC improvements •1.9.3: Lazy Sweep (@nari3) •2.0 : Bitmap Marking (@nari3) •2.1 : RGen GC (@ko1) •2.2 : Incremental GC (@ko1), 2 age RGenGC (@ko1), Symbol GC (@nari3)

Slide 98

Slide 98 text

Newer Rails

Slide 99

Slide 99 text

At RubyKaigi this year "Rails 4.2 is going to be the fastest Rails ever." @tenderlove

Slide 100

Slide 100 text

Let's try Rails 4.2!

Slide 101

Slide 101 text

Creating the same app on current GH master

Slide 102

Slide 102 text

Results • 1842ms (Views: 1450.1ms | ActiveRecord: 61.5ms) • 1908ms (Views: 1505.3ms | ActiveRecord: 60.8ms) • 1998ms (Views: 1590.2ms | ActiveRecord: 62.8ms) • 1948ms (Views: 1531.7ms | ActiveRecord: 63.2ms) • 1984ms (Views: 1561.9ms | ActiveRecord: 65.9ms)

Slide 103

Slide 103 text

No big change •Or isn't it actually slower a little bit?

Slide 104

Slide 104 text

Let's see what's happening •Aaron said he changed AR a lot, but what's actually happening when calling User.all.to_a ? •Let's see which methods were called.

Slide 105

Slide 105 text

How could we know which methods were called? "Use the Tracepoint API." @ko1

Slide 106

Slide 106 text

Tracepoint •Introduced in the core since Ruby 2.0

Slide 107

Slide 107 text

Tracing the AR query def index - @users = User.all.to_a + calls = [] + trace = TracePoint.new(:call) do |tp| + calls << [tp.defined_class, tp.method_id, tp.lineno] + end + trace.enable + @users = User.all.to_a + trace.disable + pp calls.group_by(&:itself).map {|k, v| {k => v.length}}.sort_by {|h| -h.values.first} end

Slide 108

Slide 108 text

trace output (4.2) {[ActiveRecord::Attribute, :initialize, 25]=>140000}, {[#, :from_database, 4]=>140000}, {[ActiveRecord::AttributeMethods::ClassMethods, :de ne_attribute_methods, 79]=>20000}, {[ActiveRecord::ModelSchema::ClassMethods, :inheritance_column, 186]=>20000}, {[ActiveSupport::Callbacks, :_run_callbacks, 86]=>20000}, {[ActiveSupport::Callbacks::CallbackChain, :empty?, 488]=>20000}, {[ActiveRecord::AttributeMethods::PrimaryKey::ClassMethods, :primary_key, 72]=>10014}, {[Object, :present?, 23]=>10001}, {[ActiveRecord::Persistence::ClassMethods, :instantiate, 66]=>10000}, {[#, :_ nd_callbacks, 86]=>10000}, {[ActiveRecord::AttributeSet::Builder, :add_uninitialized_attributes, 25]=>10000}, {[ActiveRecord::AttributeSet, :initialize, 7]=>10000},

Slide 109

Slide 109 text

trace output (4.1) {[ActiveSupport::Callbacks, :run_callbacks, 79]=>20001}, {[ActiveSupport::Callbacks::CallbackChain, :empty?, 485]=>20001}, {[ActiveRecord::ModelSchema::ClassMethods, :inheritance_column, 165]=>20000}, {[ActiveRecord::AttributeMethods::PrimaryKey::ClassMethods, :primary_key, 71]=>10028}, {[Object, :present?, 23]=>10001}, {[ActiveRecord::ModelSchema::ClassMethods, :decorate_columns, 230]=>10001}, {[ActiveRecord::Persistence::ClassMethods, :instantiate, 49]=>10000}, {[#, :_ nd_callbacks, 86]=>10000}, {[ActiveRecord::Base, :_ nd_callbacks, 106]=>10000}, {[ActiveRecord::AttributeMethods::ClassMethods, :de ne_attribute_methods, 70]=>10000}, {[ActiveRecord::Core, :init_internals, 431]=>10000}, {[ActiveRecord::Persistence::ClassMethods, :discriminate_class_for_record,

Slide 110

Slide 110 text

trace output (4.2) {[ActiveRecord::Attribute, :initialize, 25]=>140000}, {[#, :from_database, 4]=>140000}, {[ActiveRecord::AttributeMethods::ClassMethods, :de ne_attribute_methods, 79]=>20000}, {[ActiveRecord::ModelSchema::ClassMethods, :inheritance_column, 186]=>20000}, {[ActiveSupport::Callbacks, :_run_callbacks, 86]=>20000}, {[ActiveSupport::Callbacks::CallbackChain, :empty?, 488]=>20000}, {[ActiveRecord::AttributeMethods::PrimaryKey::ClassMethods, :primary_key, 72]=>10014}, {[Object, :present?, 23]=>10001}, {[ActiveRecord::Persistence::ClassMethods, :instantiate, 66]=>10000}, {[#, :_ nd_callbacks, 86]=>10000}, {[ActiveRecord::AttributeSet::Builder, :add_uninitialized_attributes, 25]=>10000}, {[ActiveRecord::AttributeSet, :initialize, 7]=>10000},

Slide 111

Slide 111 text

Confirming that this is actually consuming the CPU time

Slide 112

Slide 112 text

Stackprof •Use stackprof gem by @tmm1 •Available in Ruby 2.1+

Slide 113

Slide 113 text

app/controllers/ users_controller.rb def index - @users = User.all.to_a + StackProf.run(mode: :cpu, out: 'tmp/ stackprof-cpu-ar.dump') do + @users = User.all.to_a + end end

Slide 114

Slide 114 text

Rails 4.2 (GC.disabled) ================================== Mode: cpu(1000) Samples: 376 (0.00% miss rate) GC: 0 (0.00%) ================================== TOTAL (pct) SAMPLES (pct) FRAME 131 (34.8%) 131 (34.8%) ActiveRecord::Attribute#initialize 58 (15.4%) 58 (15.4%) block in SQLite3::Statement#each 176 (46.8%) 42 (11.2%) block in ActiveRecord::AttributeSet::Builder#build_attributes_from_values 39 (10.4%) 39 (10.4%) block in ActiveRecord::Result#hash_rows 16 (4.3%) 16 (4.3%) block in ActiveRecord::AttributeSet::Builder#add_uninitialized_attributes 12 (3.2%) 12 (3.2%) NilClass#blank?

Slide 115

Slide 115 text

I guess this has to be fixed before the 4.2.0 release

Slide 116

Slide 116 text

Haml

Slide 117

Slide 117 text

Haml is consuming most of the response time •Can't we make it faster?

Slide 118

Slide 118 text

So, I started creating "hamlx" •A faster Haml fork •Optimized for Rails •IOW requires Rails •(planning to be html_safe by default) •(still in progress) •(not published yet)

Slide 119

Slide 119 text

hamlx • 1616ms (Views: 1386.4ms | ActiveRecord: 69.1ms) • 1606ms (Views: 1384.0ms | ActiveRecord: 77.5ms) • 1576ms (Views: 1303.2ms | ActiveRecord: 76.9ms) • 1545ms (Views: 1303.1ms | ActiveRecord: 68.5ms) • 1585ms (Views: 1341.6ms | ActiveRecord: 65.3ms)

Slide 120

Slide 120 text

hamlx •Renderes 10ʙ20% faster than current haml gem • (still slower than slim, I guess...) •Will be shipped :soon:

Slide 121

Slide 121 text

Conclusion • Ruby is getting faster • Rails is getting faster • Now we have tools to investigate what's slow • URL helpers are extremely slow • Haml is slow • A faster Haml fork is coming soon

Slide 122

Slide 122 text

end