Patch #23334

Updated by Toshi MARUYAMA about 1 year ago

I have several issues with around 50 custom fields. When doing updates to these issues, I identified poor performance on the @editable_custom_field_values@ function being called to check if current user has access to the custom fields.

Here is the code for this method (in @app/model/issue.rb@):

<pre><code class="ruby"> &lt;pre&gt;
# Returns the custom_field_values that can be edited by the given user
def editable_custom_field_values(user=nil)
visible_custom_field_values(user).reject do |value|
read_only_attribute_names(user).include?(value.custom_field_id.to_s)
end
end
</code></pre> &lt;/pre&gt;

Here, it seems that @read_only_attribute_names(user)@ is recomputed for each @visible_custom_field_values(user)@ without caching, which will slow down the action if the issue has many custom fields associated (only if user is provided).

I have applied a simple patch (I store the result of @read_only_attribute_names(user)@ before the loop):

<pre><code class="ruby"> &lt;pre&gt;
def editable_custom_field_values(user=nil)
read_only_attr_names_array = read_only_attribute_names(user)
visible_custom_field_values(user).reject do |value|
read_only_attr_names_array.include?(value.custom_field_id.to_s)
end
end
</code></pre> &lt;/pre&gt;

Now, some results computed for an admin user, for approx 100 issues with various custom fields:

Before:
<pre>
2.2.2 :001 > puts Benchmark.measure { u = User.find(88); Issue.last(100).to_a.map{|i| i.editable_custom_field_values(u)} }
2.2.2 :002 > 102.260000 0.710000 102.970000 (103.480136)
</pre>

After:

<pre>
2.2.2 :001 > puts Benchmark.measure { u = User.find(88); Issue.last(100).to_a.map{|i| i.editable_custom_field_values(u)} }
2.2.2 :002 > 5.070000 0.090000 5.160000 ( 5.198187)
</pre>

<pre>
Environment:
Redmine version 3.3.0.stable
Ruby version 2.2.2-p95 (2015-04-13) [x86_64-linux]
Rails version 4.2.6
Environment development
Database adapter Mysql2
</pre>

Back