The parallel-gem Show archive.org snapshot is quite easy to use and can speed up rendering time if you want to render the same partial multiple times (e.g. for rendering long lists of things).
Parallel supports execution using forked processes (the default), threads (mind the GVL) and Ractors (some limitations for data sharing).
If your parallelized code talks to the database, you should ensure not to leak database connections.
Example
Consider you want to render a list of groups with their members as json. You can use a partial for the rendering of group members, because they look the same for all groups. And those partials can as well be rendered in parallel.
With parallel the rendering was 2,5 times faster in my case (the actual speedup depends on the hardware that is used to run the code).
Slow, non-parallel implementation
class GroupsController < ApplicationController
def members
group_ids = params[:group_ids].split(',')
group_ids_and_html = {}
group_ids.each do |group_id|
group = load_group(group_id)
group_ids_and_html[group_id] = render_group_html(group)
end
render json: group_ids_and_html
end
private
def load_group(group_id)
Group.find(group_id)
end
def render_group_html(user_group)
render_to_string partial: 'groups/members', locals: { group: group }
end
end
Faster implementation with Parallel
class GroupsController < ApplicationController
def members
group_ids = params[:group_ids].split(',')
group_ids_and_html = Parallel.map(group_ids) do |group_id| # <- Here is the difference
group = load_group(group_id)
[group_id, render_group_html(group)]
ensure
ActiveRecord::Base.clear_active_connections # <- close additional database connections
end
render json: Hash[*group_ids_and_html.flatten(1)]
end
private
def load_group(group_id)
Group.find(group_id)
end
def render_group_html(user_group)
render_to_string partial: 'groups/members', locals: { group: group }
end
end
Note
If you are using database-cleaner with
DatabaseCleaner.strategy = :transaction
, this could lead to problems in tests. You should useDatabaseCleaner.strategy = :truncation
for the tests that touch your parallelized code.