11
votes

I'm not sure if this is a Rails specific issue, hence the reason I tagged it ruby as well.

I'm rendering a collection of event records via a partial. However, I found that rendering the partial differently results in drastic performance differences.

Both version use the exact same data, the only thing changing is the code used to render the partials.

Why the heck is one version consistently 4x faster than the other? Makes me wonder what other performance hits I'm taking...

Slow version (950ms total request time):

<% events.each do |event| %>
  <%= render partial: "events/event", locals: { event: event } %>
<% end %>

# Log output
Rendered events/_event.html.erb (1.1ms)
Rendered events/_event.html.erb (1.1ms) 
...

Faster version (250ms total request time):

<%= render partial: "events/event", collection: events, as: :event %>

# Log output
Rendered events/_event.html.erb (58.7ms)
1
when you render a partial it compiles the html first. In the first this happens events.length times, in the second it happens only once. This situation (loops being slower) occurs in other places in Rails as well, such as DB queries. It's called "N+1"max pleaner

1 Answers

11
votes

example 1: you are rendering a partial x times (depending on events). which means you are compiling html x times(once each time the loop runs). which is slow

example 2: you are rendering one partial with a collection of events the html is compiled once(as there is only one partial). which is fast