Class: Ramaze::LRUHash
Overview
A Hash-alike LRU cache that provides fine-grained control over content restrictions.
It allows you to set:
- a maximum number of elements
- the maximum amount of memory used for all elements
- the allowed memory-size per element
- time to live
Differences to the original implementation include:
- The Cache is now a Struct for speed
- Object memory size is obtained via Marshal::dump instead of #to_s
Note that due to calculating object size with Marshal, you might have to do some evaluation as to how large your values will be when marshaled, for example a String will have String#size + 10. This differs from object to object and between versions of Marshal, so be generous.
Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org> Copyright © 2009 Michael Fellinger <manveru@rubyists.com>
You may redistribute it and/or modify it under the same terms as Ruby.
Defined Under Namespace
Classes: CacheObject
Constant Summary
- VERSION =
'0.3'- KeyError =
On 1.8 we raise IndexError, on 1.9 we raise KeyError
Module.const_defined?(:KeyError) ? KeyError : IndexError
Instance Method Summary (collapse)
- - (Object) [](key)
- - (Object) []=(key, obj)
- - (Object) clear (also: #invalidate_all)
- - (Object) delete(key) (also: #invalidate)
- - (Object) each_key(&block)
- - (Object) each_pair
- - (Object) each_value
- - (Boolean) empty?
- - (Object) expire
-
- (Object) fetch(key, default = (p_default = true; nil))
Note that this method diverges from the default behaviour of the Ruby Hash.
- - (Object) index(given_value)
-
- (LRUHash) initialize(options = {}, &hook)
constructor
A new instance of LRUHash.
- - (Boolean) key?(key)
- - (Object) keys
- - (Object) size (also: #length)
- - (Object) statistics
- - (Object) store(key, value)
- - (Object) to_hash
- - (Boolean) value?(given_value)
- - (Object) values
Methods inherited from Struct
Constructor Details
- (LRUHash) initialize(options = {}, &hook)
A new instance of LRUHash
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 35 def initialize( = {}, &hook) self.max_value = [:max_value] self.max_total = [:max_total] self.max_count = [:max_count] self.expiration = [:expiration] self.hook = hook self.objs = {} self.list = [] self.total_size = 0 self.hits = self.misses = 0 end |
Instance Method Details
- (Object) [](key)
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 121 def [](key) expire unless objs.key?(key) self.misses += 1 return end obj = objs[key] obj.atime = Time.now.to_i list.delete_if{|list_key| key == list_key } list << key self.hits += 1 obj.content end |
- (Object) []=(key, obj)
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 139 def []=(key, obj) expire invalidate key if key?(key) size = Marshal.dump(obj).size if max_value && max_value < max_total warn "%p isn't cached because it exceeds max_value %p" % [obj, max_value] return obj end if max_value.nil? && max_total && max_total < size warn "%p isn't cached because it exceeds max_total: %p" % [obj, max_total] return obj end invalidate list.first if max_count && max_count == list.size self.total_size += size if max_total invalidate list.first until total_size < max_total end objs[key] = CacheObject.new(obj, size, Time.now.to_i) list << key obj end |
- (Object) clear Also known as: invalidate_all
103 104 105 106 107 108 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 103 def clear objs.each{|key, obj| hook.call(key, obj) } if hook objs.clear list.clear self.total_size = 0 end |
- (Object) delete(key) Also known as: invalidate
89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 89 def delete(key) return unless objs.key?(key) obj = objs[key] hook.call(key, obj.content) if hook self.total_size -= obj.size objs.delete key list.delete_if{|list_key| key == list_key } obj.content end |
- (Object) each_key(&block)
180 181 182 183 184 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 180 def each_key(&block) return enum_for(:each_key) unless block_given? objs.each_key{|key| yield key } self end |
- (Object) each_pair
174 175 176 177 178 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 174 def each_pair return enum_for(:each_pair) unless block_given? objs.each{|key, obj| yield key, obj.content } self end |
- (Object) each_value
186 187 188 189 190 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 186 def each_value return enum_for(:each_value) unless block_given? objs.each_value{|obj| yield obj.content } self end |
- (Boolean) empty?
192 193 194 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 192 def empty? objs.empty? end |
- (Object) expire
111 112 113 114 115 116 117 118 119 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 111 def expire return unless expiration now = Time.now.to_i list.each_with_index do |key, index| break unless (objs[key].atime + expiration) <= now invalidate key end end |
- (Object) fetch(key, default = (p_default = true; nil))
Note that this method diverges from the default behaviour of the Ruby Hash. If the cache doesn’t find content for the given key, it will store the given default instead. Optionally it also takes a block, the return value of the block is then stored and returned.
209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 209 def fetch(key, default = (p_default = true; nil)) if key?(key) value = self[key] elsif p_default.nil? value = self[key] = default elsif block_given? value = self[key] = yield(key) else raise KeyError, "key not found: %p" % [key] end value end |
- (Object) index(given_value)
64 65 66 67 68 69 70 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 64 def index(given_value) objs.each do |key, obj| return key if given_value == obj.content end nil end |
- (Boolean) key?(key)
52 53 54 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 52 def key?(key) objs.key?(key) end |
- (Object) keys
72 73 74 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 72 def keys objs.keys end |
- (Object) size Also known as: length
76 77 78 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 76 def size objs.size end |
- (Object) statistics
223 224 225 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 223 def statistics {:size => total_size, :count => list.size, :hits => hits, :misses => misses} end |
- (Object) store(key, value)
170 171 172 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 170 def store(key, value) self[key] = value end |
- (Object) to_hash
81 82 83 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 81 def to_hash objs.dup end |
- (Boolean) value?(given_value)
56 57 58 59 60 61 62 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 56 def value?(given_value) objs.each do |key, obj| return true if given_value == obj.content end false end |
- (Object) values
85 86 87 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 85 def values objs.map{|key, obj| obj.content } end |