-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Cache interpolator methods and reduce memory allocations #1888
Conversation
end | ||
|
||
def self.tag_pattern_cache | ||
@tag_pattern_cache ||= Hash.new {|hash, key| hash[key]= ":#{key}"} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Surrounding space missing for operator '='.
Space between { and | missing.
Space missing inside }.
in my use case, as referred in #1882, it behaves quite better (with some room for improvements :) ). see bellow for the difference between current master and this PR. with current master version, commit 7f732ee
with this PR, commit 9f96d82
|
+1 |
end | ||
|
||
it 'pluralizes and underscore words' do | ||
it 'pluralizes and underscore class names' do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.
I've added some additional performance tunings related to interpolation. These changes bring another 50% speed improvement by optimizing the individual interpolation methods. These gains are primarily through using The benchmark script I'm using is here... https://gist.github.com/dgynn/1d8380ee57999597db2f Running that benchmark against master (947fbf6), the interim commit (June 7), and the latest commit using MemoryProfiler results in the following counts for generating one Master
Total allocated: 74513 bytes (547 objects)
Total retained: 2069 bytes (17 objects)
Interim
Total allocated: 12640 bytes (125 objects)
Total retained: 2449 bytes (22 objects)
Latest
Total allocated: 8128 bytes (84 objects)
Total retained: 2129 bytes (20 objects) The Benchmark IPS results show a 6x+ improvement of... Master
original style 3.657k (± 1.3%) i/s - 18.480k
style without format 3.536k (± 1.6%) i/s - 17.813k
style with format 3.198k (±12.6%) i/s - 15.792k
Interim
original style 15.788k (± 1.9%) i/s - 78.999k
style without format 14.885k (± 3.0%) i/s - 75.550k
style with format 15.459k (± 1.7%) i/s - 78.008k
Latest
original style 23.203k (± 2.4%) i/s - 118.206k
style without format 22.330k (± 1.1%) i/s - 112.372k
style with format 23.181k (± 1.4%) i/s - 117.208k |
@@ -148,7 +148,7 @@ def sanitize_hash(hash) | |||
Proc.new do |style, attachment| | |||
permission = (@s3_permissions[style.to_s.to_sym] || @s3_permissions[:default]) | |||
permission = permission.call(attachment, style) if permission.respond_to?(:call) | |||
(permission == DEFAULT_PERMISSION) ? 'http' : 'https' | |||
(permission == DEFAULT_PERMISSION) ? 'http'.freeze : 'https'.freeze |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line is too long. [81/80]
Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.
Thanks @jyurek. This branch is mergeable now and the specs should be passing. Let me know if you want this squashed/rebased at all. |
Hey @dgynn I'm still getting some conflicts in |
by using the attachment name (symbol) and Class as keys we reduce the number of Strings created before hitting the cache
this commit primarily uses frozen strings to reduce object creation during interpolation. the :basename method now uses File.basename(file, ".*") rather than a Regexp. basename may be called multiple times.
the name string is used multiple times in interpolation so storing it reduces object creation
372c499
to
c77ca63
Compare
@jyurek I've rebased against master and cleaned up that conflict. Thanks for merging this. |
@tute Can you see about merging this branch too? The Travis failure was just 1 test not running fast enough. This should be good to merge. Let me know if it isn't. |
Thanks! It does rebase cleanly now, and I restarted the two jobs that failed. Would love a review of @schneems too, in case he spots any potential issue or potential further performance gains. Thank you all! |
@tute I'd love to get this merged as part of the 4.2.x release before the upgrade to 5.0 if that is possible. |
👍 all the perf pieces look good. Any chance someone is relying on internal class methods like Great job 👏 |
Thanks for your work @dgynn, and for your review @schneems!
That's a good point. Any thoughts on that, @jyurek?
Sounds good to me. In that case, the PR should be rebased on top of (and reopened against) |
Thanks for the review @schneems. For the PluralCache, I was thinking it was unlikely that anyone would be relying on it. @jyurek, let me know if you think it should be added back with a deprecation warning. I've just submitted PR #2051 to get master back to green. If that PR is OK and can get merged I'll rebase on that and then look at doing the same on v4.3. |
It doesn't look like many people would use it, just wanted an opinion from someone closer to the project. |
I agree that this API change should be fine. @dgynn PR is green! Rebase on top of 4.3 and release? |
@tute I've opened 2 PRs that are rebased against master #2054 and against v4.3 #2056. I'm good with either or both of them getting merged and a release of 4.3 would be great. Sorry for so many PRs. I didn't want to rebase this branch because I have a few apps pointing at it that need to get updated. |
Thank you! I merged into v4.3 #2056, and when that branch is green on CI (and when I have the time, in less than a week I'd expect!), I'll release a patch release with this, that we can then merge into master. Thanks so much! 😃 👏 🎉 ❤️ |
The
Paperclip::Interpolations
module generates a lot of objects. As noted in #1882 there is memory allocated to get the list of interpolation methods and then again whengsub
is called.This commit memoizes the array of interpolation methods and the key-to-symbol mappings. It then uses
gsub!
to manipulate the result only when a key matches. The interpolation method cache is reset if any new interpolation is added.I've benchmarked it using a simple
Attachment
object configured to use :s3 and callingmy_attachment.url(:thumb)
. The cached version is 4.5x faster and uses about 85% less memory. This is separate from the improvements in #1873 (which were also great).There are still some tunings that could be done on the individual interpolations, like freezing strings. This commit doesn't address those.
Benchmark IPS comparison
MemoryProfiler before:
Memory Profiler after