Class: Fontisan::Variation::Cache
- Inherits:
-
Object
- Object
- Fontisan::Variation::Cache
- Defined in:
- lib/fontisan/variation/cache.rb
Overview
Caches variation calculations for performance
This class implements a caching layer for expensive variation calculations to significantly improve instance generation performance. It caches:
-
Normalized scalars per coordinate set
-
Interpolated values
-
Instance generation results
-
Region matches
Cache strategies:
-
LRU (Least Recently Used) for memory management
-
Coordinate-based keys for scalar caching
-
Invalidation on font modification
-
Optional persistent caching across sessions
Direct Known Subclasses
Instance Attribute Summary collapse
-
#max_size ⇒ Integer
readonly
Maximum cache size.
-
#stats ⇒ Hash
readonly
Cache statistics.
Instance Method Summary collapse
-
#cached?(key) ⇒ Boolean
Check if key is cached and valid.
-
#clear ⇒ Object
Clear entire cache.
-
#empty? ⇒ Boolean
Check if cache is empty.
-
#fetch(key) { ... } ⇒ Object
Generic fetch with caching.
-
#fetch_instance(font_checksum, coordinates) { ... } ⇒ Hash
Fetch or compute instance generation result.
-
#fetch_interpolated(base_value, deltas, scalars) { ... } ⇒ Float
Fetch or compute interpolated value.
-
#fetch_region_matches(coordinates, regions) { ... } ⇒ Array
Fetch or compute region matches.
-
#fetch_scalars(coordinates, axes) { ... } ⇒ Array<Float>
Fetch or compute scalars for coordinates.
-
#full? ⇒ Boolean
Check if cache is full.
-
#initialize(max_size: 1000, ttl: nil) ⇒ Cache
constructor
Initialize cache.
-
#invalidate(key) ⇒ Object
Invalidate specific key.
-
#invalidate_matching(pattern) ⇒ Object
Invalidate keys matching pattern.
-
#size ⇒ Integer
Get cache size.
-
#statistics ⇒ Hash
Get cache statistics.
-
#store(key, value) ⇒ Object
Store value in cache.
Constructor Details
#initialize(max_size: 1000, ttl: nil) ⇒ Cache
Initialize cache
42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/fontisan/variation/cache.rb', line 42 def initialize(max_size: 1000, ttl: nil) @max_size = max_size @ttl = ttl @cache = {} @access_times = {} @stats = { hits: 0, misses: 0, evictions: 0, invalidations: 0, } end |
Instance Attribute Details
#max_size ⇒ Integer (readonly)
Returns Maximum cache size.
33 34 35 |
# File 'lib/fontisan/variation/cache.rb', line 33 def max_size @max_size end |
#stats ⇒ Hash (readonly)
Returns Cache statistics.
36 37 38 |
# File 'lib/fontisan/variation/cache.rb', line 36 def stats @stats end |
Instance Method Details
#cached?(key) ⇒ Boolean
Check if key is cached and valid
122 123 124 125 126 127 |
# File 'lib/fontisan/variation/cache.rb', line 122 def cached?(key) return false unless @cache.key?(key) return false if expired?(key) true end |
#clear ⇒ Object
Clear entire cache
144 145 146 147 148 |
# File 'lib/fontisan/variation/cache.rb', line 144 def clear @cache.clear @access_times.clear @stats[:invalidations] += 1 end |
#empty? ⇒ Boolean
Check if cache is empty
192 193 194 |
# File 'lib/fontisan/variation/cache.rb', line 192 def empty? @cache.empty? end |
#fetch(key) { ... } ⇒ Object
Generic fetch with caching
105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/fontisan/variation/cache.rb', line 105 def fetch(key) if cached?(key) @stats[:hits] += 1 touch(key) return @cache[key][:value] end @stats[:misses] += 1 value = yield store(key, value) value end |
#fetch_instance(font_checksum, coordinates) { ... } ⇒ Hash
Fetch or compute instance generation result
84 85 86 87 |
# File 'lib/fontisan/variation/cache.rb', line 84 def fetch_instance(font_checksum, coordinates, &) key = CacheKeyBuilder.instance_key(font_checksum, coordinates) fetch(key, &) end |
#fetch_interpolated(base_value, deltas, scalars) { ... } ⇒ Float
Fetch or compute interpolated value
73 74 75 76 |
# File 'lib/fontisan/variation/cache.rb', line 73 def fetch_interpolated(base_value, deltas, scalars, &) key = CacheKeyBuilder.interpolation_key(base_value, deltas, scalars) fetch(key, &) end |
#fetch_region_matches(coordinates, regions) { ... } ⇒ Array
Fetch or compute region matches
95 96 97 98 |
# File 'lib/fontisan/variation/cache.rb', line 95 def fetch_region_matches(coordinates, regions, &) key = CacheKeyBuilder.region_matches_key(coordinates, regions) fetch(key, &) end |
#fetch_scalars(coordinates, axes) { ... } ⇒ Array<Float>
Fetch or compute scalars for coordinates
61 62 63 64 |
# File 'lib/fontisan/variation/cache.rb', line 61 def fetch_scalars(coordinates, axes, &) key = CacheKeyBuilder.scalars_key(coordinates, axes) fetch(key, &) end |
#full? ⇒ Boolean
Check if cache is full
199 200 201 |
# File 'lib/fontisan/variation/cache.rb', line 199 def full? @cache.size >= @max_size end |
#invalidate(key) ⇒ Object
Invalidate specific key
153 154 155 156 157 |
# File 'lib/fontisan/variation/cache.rb', line 153 def invalidate(key) @cache.delete(key) @access_times.delete(key) @stats[:invalidations] += 1 end |
#invalidate_matching(pattern) ⇒ Object
Invalidate keys matching pattern
162 163 164 165 |
# File 'lib/fontisan/variation/cache.rb', line 162 def invalidate_matching(pattern) keys = @cache.keys.select { |k| k.match?(pattern) } keys.each { |k| invalidate(k) } end |
#size ⇒ Integer
Get cache size
185 186 187 |
# File 'lib/fontisan/variation/cache.rb', line 185 def size @cache.size end |
#statistics ⇒ Hash
Get cache statistics
170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/fontisan/variation/cache.rb', line 170 def statistics total = @stats[:hits] + @stats[:misses] hit_rate = total.zero? ? 0.0 : @stats[:hits].to_f / total @stats.merge( total_requests: total, hit_rate: hit_rate, size: @cache.size, max_size: @max_size, ) end |
#store(key, value) ⇒ Object
Store value in cache
133 134 135 136 137 138 139 140 141 |
# File 'lib/fontisan/variation/cache.rb', line 133 def store(key, value) evict_if_needed @cache[key] = { value: value, created_at: Time.now, } touch(key) end |