From 066919f245e181dd2a9986343e3fabb3c4485fef Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Wed, 14 Mar 2018 13:42:40 -0600 Subject: Don't marshal ActiveSupport::Cache::Entry objects twice When upgrading to Rails 5.2 we're seeing `ActiveSupport::Cache::Entry#compress` and `ActiveSupport::Cache::Entry#should_compress?` as the highest usage of our CPU. At least some part of this is coming from the fact that objects are being marshaled multiple times. This memoizes the marshaled value to eliminate half the problem. --- activesupport/lib/active_support/cache.rb | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index 1ea2d0bbf2..6967c164ab 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -714,11 +714,9 @@ module ActiveSupport # Creates a new cache entry for the specified value. Options supported are # +:compress+, +:compress_threshold+, and +:expires_in+. def initialize(value, options = {}) - if should_compress?(value, options) - @value = compress(value) - @compressed = true - else - @value = value + @value = value + if should_compress?(options) + compress! end @version = options[:version] @@ -783,28 +781,31 @@ module ActiveSupport end private - def should_compress?(value, options) - if value && options.fetch(:compress, true) + def should_compress?(options) + if @value && options.fetch(:compress, true) compress_threshold = options.fetch(:compress_threshold, DEFAULT_COMPRESS_LIMIT) - serialized_value_size = (value.is_a?(String) ? value : Marshal.dump(value)).bytesize + serialized_value_size = (@value.is_a?(String) ? @value : marshaled_value).bytesize - return true if serialized_value_size >= compress_threshold + serialized_value_size >= compress_threshold end - - false end def compressed? defined?(@compressed) ? @compressed : false end - def compress(value) - Zlib::Deflate.deflate(Marshal.dump(value)) + def compress! + @value = Zlib::Deflate.deflate(marshaled_value) + @compressed = true end def uncompress(value) Marshal.load(Zlib::Inflate.inflate(value)) end + + def marshaled_value + @marshaled_value ||= Marshal.dump(@value) + end end end end -- cgit v1.2.3