プロジェクト

全般

プロフィール

Vote #79461

完了

Switch to mini_mime from mime-types

Admin Redmine さんが3年以上前に追加. 3年以上前に更新.

ステータス:
Closed
優先度:
通常
担当者:
-
カテゴリ:
Performance_53
対象バージョン:
開始日:
2022/05/09
期日:
進捗率:

0%

予定工数:
category_id:
53
version_id:
99
issue_org_id:
29359
author_id:
123153
assigned_to_id:
332
comments:
22
status_id:
5
tracker_id:
3
plus1:
0
affected_version:
closed_on:
affected_version_id:
ステータス-->[Closed]

説明

Redmine uses unbound cache for mime types which is eliminated now. Also mime-types is too heavy and Redmine uses only a tiny peace of it, we just need a simple ext -> mime lookup.

https://github.com/mikel/mail/pull/1059 (mail 2.6.x still uses mime-types)
https://github.com/teamcapybara/capybara/pull/1884

require 'benchmark/ips'

Benchmark.ips do |x|
  x.report('known')     { Redmine::MimeType.of("file.patch") }
  x.report('not known') { Redmine::MimeType.of("file.zip")   }
end
trunk
               known    284.431k (± 1.9%) i/s -      1.422M in   5.002378s
           not known    285.699k (± 3.0%) i/s -      1.446M in   5.065113s
patch
               known    657.114k (± 1.8%) i/s -      3.327M in   5.064494s
           not known    392.574k (± 2.2%) i/s -      1.965M in   5.006827s
                boot allocations boot retained
mime-types                109796         31165
mini_mime                    398            62

what do you think?


journals

Thank you for posting the interesting improvement.

Your patch is very fast, but I think an application should not have codes which rely on the internal structure of third-party libraries. Your patch accesses mini_mime's instance variable '@db'.

I updated your patch not to manipulate an internal variable of mini_mime. It is 15% slower than your patch but 70% faster than the current @Redmine::MimeType.of@.

without patches:
<pre>
known 226.301k (± 5.0%) i/s - 1.131M in 5.010006s
unknown 225.491k (± 4.6%) i/s - 1.131M in 5.024550s
</pre>

replace-mime-types-with-mini_mime.diff: (faster):
<pre>
known 382.020k (± 6.2%) i/s - 1.923M in 5.052268s
unknown 382.602k (± 6.6%) i/s - 1.908M in 5.008955s
</pre>

mime_type.rb.patch by Pavel Rosický (fastest):
<pre>
known 431.349k (± 5.4%) i/s - 2.167M in 5.038918s
unknown 432.307k (± 5.5%) i/s - 2.172M in 5.040046s
</pre>

--------------------------------------------------------------------------------
Sorry, there was a problem with my benchmark script. After fixing the problem, I found that my patch is very slow for unknown extensions.

without patches:
<pre>
known 170.009k (± 7.2%) i/s - 859.560k in 5.083952s
unknown 169.572k (± 6.2%) i/s - 844.816k in 5.000900s
</pre>

replace-mime-types-with-mini_mime.diff:
<pre>
known 244.827k (± 5.3%) i/s - 1.228M in 5.031343s
unknown 79.055k (± 5.5%) i/s - 394.128k in 5.000338s
</pre>

mime_type.rb.patch by Pavel Rosický:
<pre>
known 256.660k (± 5.7%) i/s - 1.291M in 5.047902s
unknown 150.151k (± 5.5%) i/s - 753.483k in 5.033494s
</pre>

<pre><code class="ruby">
require 'benchmark/ips'
require 'mini_mime'
require './lib/redmine/mime_type'

Benchmark.ips do |x|
x.report('known') { Redmine::MimeType.of('file.txt') }
x.report('unknown') { Redmine::MimeType.of('file.zip') }
end
</code></pre>
--------------------------------------------------------------------------------
I updated my patch to preserve existing cache mechanism. Now it is fast also for unknown extensions.

<pre>
known 232.028k (± 4.9%) i/s - 1.170M in 5.052806s
unknown 236.938k (± 4.6%) i/s - 1.199M in 5.071712s
</pre>
--------------------------------------------------------------------------------
Lets ask sam saffron if he could add it to the public api.
--------------------------------------------------------------------------------
@known_types is a class variable. There're two problems:
It isn't threadsafe.
It's unlimited and because it's related to user's actions it could grow indefinetly. This memory won't be released. That's why I was trying to avoid it or limit it. Minimime has the upper bound for caches. Please correct me if I'm wrong.
--------------------------------------------------------------------------------
Pavel Rosický wrote:
> @known_types is a class variable. There're two problems:
> It isn't threadsafe.
> It's unlimited and because it's related to user's actions it could grow indefinetly. This memory won't be released.

Although the patch still has the same problem with the current implementation, simply replacing mime-types with mini_mime will reduce memory usage and improve performance.

I suggest that we discuss the problem as a new issue, after committing the patch. Is it OK with you?
--------------------------------------------------------------------------------
It's ok, thanks
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
Committed. Thank you for your contribution.
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
please also remove
<pre>
require 'mime/types'
</pre>
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
Pavel Rosický wrote:
> please also remove
> [...]

Committed. Thanks.
--------------------------------------------------------------------------------
mini_mime 1.0.1 supports @lookup_by_extension@. We can remove the cache mechanism using @known_types@ hash by making use of the new method. Attaching a patch to remove the hash.

Even without the cache mechanism, @Redmine::MimeTypes.of@ is faster than the original code.

r17467 (before applying replace-mime-types-with-mini_mime-v3.diff):
<pre>
Warming up --------------------------------------
known 20.028k i/100ms
unknown 12.677k i/100ms
Calculating -------------------------------------
known 246.855k (± 6.0%) i/s - 1.242M in 5.049235s
unknown 138.044k (± 5.9%) i/s - 697.235k in 5.068005s
</pre>

with the patch 29359-remove-known-types-hash.patch:
<pre>
Warming up --------------------------------------
known 20.249k i/100ms
unknown 11.787k i/100ms
Calculating -------------------------------------
known 264.152k (± 8.0%) i/s - 1.316M in 5.015411s
unknown 142.650k (± 8.6%) i/s - 719.007k in 5.076025s
</pre>
--------------------------------------------------------------------------------
29359-remove-known-types-hash.patch - .downcase shouldn't be removed, both EXTENSIONS[] and lookup_by_extension expect lower-case

and the benchmark looks odd, in r17467 both known/unknown scenarios were cached in a class var, so I would expect simmilar performance
--------------------------------------------------------------------------------
Pavel Rosický wrote:
> 29359-remove-known-types-hash.patch - .downcase shouldn't be removed, both EXTENSIONS[] and lookup_by_extension expect lower-case

Fixed.

> and the benchmark looks odd, in r17467 both known/unknown scenarios were cached in a class var, so I would expect simmilar performance

You are right. Maybe I pasted a wrong result. The following results are correct ones. @Redmine::MimeType.of@ will be faster than r17467 in many cases.

r17467 (before switching to mini_mime):
<pre>
found in array (file.patch)
164.476k (± 6.5%) i/s - 832.300k in 5.081748s
found in gem (file.zip)
167.251k (± 5.7%) i/s - 841.580k in 5.047872s
not found in gem (file.go)
168.700k (± 5.7%) i/s - 851.440k in 5.063132s
</pre>

with the patch:
<pre>
found in array (file.patch)
418.181k (± 6.0%) i/s - 2.099M in 5.036624s
found in gem (file.zip)
183.820k (± 6.9%) i/s - 923.232k in 5.047995s
not found in gem (file.go)
147.241k (± 6.7%) i/s - 734.046k in 5.007225s
</pre>

benchmark script:
<pre><code class="ruby">
require 'benchmark/ips'
require 'mini_mime'
require './lib/redmine/mime_type'

Benchmark.ips do |x|
x.report('found in array (file.patch)') { Redmine::MimeType.of('file.patch') }
x.report('found in gem (file.zip)') { Redmine::MimeType.of('file.zip') }
x.report('not found in gem (file.go)') { Redmine::MimeType.of('file.go') }
end
</code></pre>
--------------------------------------------------------------------------------
my results (ruby 2.5.0):

with the patch (mini_mime)
<pre>
found in array (file.patch)
1.079M (± 1.9%) i/s - 5.407M in 5.011560s
found in gem (file.zip)
486.991k (± 2.6%) i/s - 2.456M in 5.047320s
not found in gem (file.go)
428.810k (± 2.3%) i/s - 2.174M in 5.072125s
</pre>

r17467 (mime_types)
<pre>
found in array (file.patch)
293.348k (± 1.6%) i/s - 1.477M in 5.035304s
found in gem (file.zip)
295.426k (± 1.8%) i/s - 1.500M in 5.080399s
not found in gem (file.go)
293.534k (± 5.3%) i/s - 1.477M in 5.048996s
</pre>

r17467 (mime_types without @known_types cache)
<pre>
found in array (file.patch)
298.984k (± 5.2%) i/s - 1.499M in 5.027456s
found in gem (file.zip)
60.804k (± 1.6%) i/s - 304.803k in 5.014262s
not found in gem (file.go)
65.405k (± 2.9%) i/s - 332.575k in 5.089481s
</pre>
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
Committed 29359-remove-known-types-hash-v2.patch.
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------


related_issues

relates,Closed,29365,MailHandlerTest#test_add_issue_with_localized_attributes fails with mail gem 2.7.0
relates,Closed,29383,Update mini_mime gem (~> 1.0.1)
relates,Closed,29443,Update mail gem (~> 2.7.1)

Admin Redmine さんが3年以上前に更新

  • カテゴリPerformance_53 にセット
  • 対象バージョン4.0.0_99 にセット

他の形式にエクスポート: Atom PDF

いいね!0
いいね!0