From 51d9b9a821a8f3f11fc5f52321df6ee05e4e1327 Mon Sep 17 00:00:00 2001 From: Simeon Simeonov Date: Sat, 20 Jul 2013 23:08:06 -0400 Subject: [Fixes #11512] improves cache size calculation in ActiveSupport::Cache::MemoryStore Previously, the cache size of `ActiveSupport::Cache::MemoryStore` was calculated as the sum of the size of its entries, ignoring the size of keys and any data structure overhead. This could lead to the calculated cache size sometimes being 10-100x smaller than the memory used, e.g., in the case of small values. The size of a key/entry pair is now calculated via `#cached_size`: def cached_size(key, entry) key.to_s.bytesize + entry.size + PER_ENTRY_OVERHEAD end The value of `PER_ENTRY_OVERHEAD` is 240 bytes based on an [empirical estimation](https://gist.github.com/ssimeonov/6047200) for 64-bit MRI on 1.9.3 and 2.0. Fixes GH#11512 https://github.com/rails/rails/issues/11512 --- activesupport/lib/active_support/cache/memory_store.rb | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/cache/memory_store.rb b/activesupport/lib/active_support/cache/memory_store.rb index 4d26fb7e42..b0aae54aa4 100644 --- a/activesupport/lib/active_support/cache/memory_store.rb +++ b/activesupport/lib/active_support/cache/memory_store.rb @@ -122,6 +122,14 @@ module ActiveSupport end protected + + # See https://gist.github.com/ssimeonov/6047200 + PER_ENTRY_OVERHEAD = 240 + + def cached_size(key, entry) + key.to_s.bytesize + entry.size + PER_ENTRY_OVERHEAD + end + def read_entry(key, options) # :nodoc: entry = @data[key] synchronize do @@ -139,8 +147,11 @@ module ActiveSupport synchronize do old_entry = @data[key] return false if @data.key?(key) && options[:unless_exist] - @cache_size -= old_entry.size if old_entry - @cache_size += entry.size + if old_entry + @cache_size -= (old_entry.size - entry.size) + else + @cache_size += cached_size(key, entry) + end @key_access[key] = Time.now.to_f @data[key] = entry prune(@max_size * 0.75, @max_prune_time) if @cache_size > @max_size @@ -152,7 +163,7 @@ module ActiveSupport synchronize do @key_access.delete(key) entry = @data.delete(key) - @cache_size -= entry.size if entry + @cache_size -= cached_size(key, entry) if entry !!entry end end -- cgit v1.2.3