Commit 3025b711 authored by Yorick Peterse's avatar Yorick Peterse

Improve ProjectTeam#max_member_access performance

By comparing objects in Ruby we can greatly improve the performance of
this method. In the worst case (should no data be eager loaded) this
will run the same amount of queries as before, in the best case (when
data _is_ eager loadeD) it requires no queries at all.

The added benchmark used to produce around 273 iterations per second.
With this commit this has been increased to almost 40 000 iterations per
second: a speedup of roughly 145 times.

Combined with eager loading Note associations this results in about 30
queries less when viewing a single issue, this in turn cuts down the
loading time by 30-40%.
parent b5f8161d
...@@ -139,15 +139,28 @@ class ProjectTeam ...@@ -139,15 +139,28 @@ class ProjectTeam
Gitlab::Access.options.key max_member_access(user_id) Gitlab::Access.options.key max_member_access(user_id)
end end
# This method assumes project and group members are eager loaded for optimal
# performance.
def max_member_access(user_id) def max_member_access(user_id)
access = [] access = []
access << project.project_members.find_by(user_id: user_id).try(:access_field)
project.project_members.each do |member|
if member.user_id == user_id
access << member.access_field if member.access_field
break
end
end
if group if group
access << group.group_members.find_by(user_id: user_id).try(:access_field) group.group_members.each do |member|
if member.user_id == user_id
access << member.access_field if member.access_field
break
end
end
end end
access.compact.max access.max
end end
private private
......
require 'spec_helper'
describe ProjectTeam, benchmark: true do
describe '#max_member_access' do
let(:group) { create(:group) }
let(:project) { create(:empty_project, group: group) }
let(:user) { create(:user) }
before do
project.team << [user, :master]
5.times do
project.team << [create(:user), :reporter]
project.group.add_user(create(:user), :reporter)
end
end
benchmark_subject { project.team.max_member_access(user.id) }
it { is_expected.to iterate_per_second(35000) }
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment