This document discusses optimizing a Rails project. It begins by noting that premature optimization is not good, and then explores various techniques to improve performance, such as reducing database queries through includes and reducing view rendering time by caching fragments. It also covers optimizing middleware, using tools like New Relic and Ruby Prof to identify bottlenecks, parallelizing with Unicorn, and targeting specific improvements identified by profiling. The overall focus is on iteratively profiling, identifying issues, and implementing solutions to gradually improve performance.
8. Apache Benchmark
ab -n 1 -c 1 http://localhost:3000/politicos/piores
9. Resultado de 1 requisição
ab -n 1 -c 1 http://localhost:3000/politicos/piores
Time taken for tests: 1.239 seconds
Requests per second: 0.81 [#/sec]
Time per request: 1239.403 [ms]
10. Resultado de 400 por 20
ab -n 400 -c 20 http://localhost:3000/politicos/piores
Time taken for tests: 595.433 seconds
Requests per second: 0.67 [#/sec]
Time per request: 1488.583 [ms]
17. Agrupando no controller
@query = Avaliacao.
where(politico_id: @politicos, eleitor_id: @eleitor)
@avaliacoes = @query.reduce({}) do |grupo, avaliacao|
grupo[avaliacao.politico_id] = avaliacao
grupo
end
18. Usando na view
Antes:
@politico.avaliacoes.do_eleitor(@eleitor)
Agora:
@avaliacoes[@politico.id]
19. Queries
SELECT `avaliacoes`.* FROM `avaliacoes`
WHERE `avaliacoes`.`politico_id`
IN (640, 620, 639, 683, ...)
AND `avaliacoes`.`eleitor_id` = 6275
> rm log/production.log
> GET http://localhost:3000/politicos/piores
> grep -c select log/production.log
7
20. Apache Benchmark
ab -n 1 -c 1 http://localhost:3000/politicos/piores
Time taken for tests: 0.658 seconds
Requests per second: 1.52 [#/sec]
Time per request: 658.123 [ms]
ab -n 400 -c 20 http://localhost:3000/politicos/piores
Time taken for tests: 298.956 seconds
Requests per second: 1.34 [#/sec]
Time per request: 747.390 [ms]
23. Cache dos filtros
def cargos_for_select
Rails.cache.fetch('cargos_for_select') do
Cargo.all.collect do |cargo|
[ cargo.no_plural, cargo.slug ]
end
end
end
<%= options_for_select(cargos_for_select) %>
25. Resultado
ab -n 400 -c 20 http://localhost:3000/politicos/piores
Time taken for tests: 300.668 seconds
Requests per second: 1.33 [#/sec]
Time per request: 751.671 [ms]
31. Unicorn
worker_processes 4
preload_app true
timeout 30
Listen 3000
after_fork do |server, worker|
ActiveRecord::Base.establish_connection
end
32. Resultado
ab -n 400 -c 20 http://localhost:3000/politicos/piores
Time taken for tests: 109.909 seconds
Requests per second: 3.64 [#/sec]
Time per request: 274.773 [ms]
43. Transformando ERBs em Str
def botoes_para_avaliar(politico, avaliacao)
html = <<-RETORNO
<div class="avaliar">
#{texto_de_avaliacao avaliacao}:<br/>
#{html_de_avaliacao_negativa politico, avaliacao}
#{html_de_avaliacao_positiva politico, avaliacao}
</div>
RETORNO
html.html_safe
end
44. O que o GC nos diz
Antes:
allocated: 46409K total in 65930 allocations,
GC calls: 6,
GC time: 262 msec
2852 a menos
Depois:
allocated: 45466K total in 63078 allocations,
GC calls: 6,
GC time: 261 msec
45. E o Apache Benchmark
ab -n 400 -c 20 http://localhost:3000/politicos/piores
Time taken for tests: 82.318 seconds
Requests per second: 4.86 [#/sec]
Time per request: 205.796 [ms]
49. Benchmark
Benchmark.measure do
1000.times do |i|
Rails.cache.write("a#{i}",i)
Rails.cache.read("a#{i}")
end
end
Memcache-client:
=> 0.860000 0.020000 0.880000 ( 0.880819)
Dalli:
=> 0.270000 0.020000 0.290000 ( 0.302308)
50. Resultado
ab -n 400 -c 20 http://localhost:3000/politicos/piores
Time taken for tests: 80.309 seconds
Requests per second: 4.98 [#/sec]
Time per request: 200.773 [ms]
52. O que o ruby-prof nos diz...
41% do seu
processamento
antes
53. Rack Middlewares
> RAILS_ENV=production rake middleware
use Rack::Cache
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x0000000293e930>
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::RemoteIp
use Rack::Sendfile
use ActionDispatch::Callbacks
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use ActionDispatch::Head
use Rack::ConditionalGet
use Rack::ETag
use ActionDispatch::BestStandardsSupport
use ExceptionNotifier
use OmniAuth::Builder
run Webcracia::Application.routes
56. O que o GC nos diz...
Antes:
allocated: 45466K total in 63078 allocations,
GC calls: 6,
GC time: 261 msec
1111 a menos
Antes:
allocated: 45329K total in 61967 allocations,
GC calls: 6,
GC time: 250 msec
57. E o Apache Benchmark
ab -n 400 -c 20 http://localhost:3000/politicos/piores
Time taken for tests: 75.588 seconds
Requests per second: 5.29 [#/sec]
Time per request: 188.970 [ms]
60. Mais cache
def html_de_filtros
Rails.cache.fetch('filtros') do
html = <<-RETORNO
<div class="filtros">Filtrar por:<br/>
#{select_de_cargos}
#{select_de_partidos}
#{select_de_estados}
</div>"
RETORNO
html.html_safe
end
end
61. Resultado
ab -n 400 -c 20 http://localhost:3000/politicos/piores
Time taken for tests: 73.719 seconds
Requests per second: 5.43 [#/sec]
Time per request: 184.296 [ms]