memery 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +1 -1
- data/.rubocop.yml +1 -1
- data/Gemfile.lock +41 -41
- data/README.md +30 -0
- data/benchmark.rb +26 -0
- data/lib/memery/version.rb +1 -1
- data/lib/memery.rb +15 -4
- data/memery.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 56c60aff8199aebc5f2b15e9b777937eea73a7246c61b265c2f6ee980b6dbcd1
|
4
|
+
data.tar.gz: f16d9b904ded0d29ca13a7a3690f07e4ecec2cb681e56fce6c390db75a20e4cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55a891049c8df688bad894e69ece34b11e4319ce1e00c63a081b01df728918661ff1bc7148f0278c20f1c5fa150eca036fcb3b3f7a35b13c859a7552e5f2d39f
|
7
|
+
data.tar.gz: 491214a08cf1286d6dc908f8972c02c9273b5b8e571cc894e377ab425a965fe0997a5053cd6ab3faae240af0a78159e2cc3418d08b74d8639e2f133d6f54dc27
|
data/.github/workflows/ci.yml
CHANGED
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,111 +1,109 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
memery (1.
|
4
|
+
memery (1.7.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
activesupport (7.1.
|
9
|
+
activesupport (7.1.5.1)
|
10
10
|
base64
|
11
|
+
benchmark (>= 0.3)
|
11
12
|
bigdecimal
|
12
13
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
13
14
|
connection_pool (>= 2.2.5)
|
14
15
|
drb
|
15
16
|
i18n (>= 1.6, < 2)
|
17
|
+
logger (>= 1.4.2)
|
16
18
|
minitest (>= 5.1)
|
17
19
|
mutex_m
|
20
|
+
securerandom (>= 0.3)
|
18
21
|
tzinfo (~> 2.0)
|
19
22
|
ast (2.4.2)
|
20
23
|
base64 (0.2.0)
|
24
|
+
benchmark (0.4.0)
|
21
25
|
benchmark-ips (2.14.0)
|
22
26
|
benchmark-memory (0.2.0)
|
23
27
|
memory_profiler (~> 1)
|
24
|
-
bigdecimal (3.1.
|
28
|
+
bigdecimal (3.1.9)
|
25
29
|
coderay (1.1.3)
|
26
30
|
concurrent-ruby (1.3.4)
|
27
31
|
connection_pool (2.4.1)
|
28
32
|
diff-lcs (1.5.1)
|
29
33
|
docile (1.4.1)
|
30
34
|
drb (2.2.1)
|
31
|
-
i18n (1.14.
|
35
|
+
i18n (1.14.6)
|
32
36
|
concurrent-ruby (~> 1.0)
|
33
|
-
json (2.
|
37
|
+
json (2.9.1)
|
34
38
|
language_server-protocol (3.17.0.3)
|
39
|
+
logger (1.6.4)
|
35
40
|
memory_profiler (1.0.2)
|
36
41
|
method_source (1.1.0)
|
37
|
-
minitest (5.25.
|
38
|
-
mutex_m (0.
|
42
|
+
minitest (5.25.4)
|
43
|
+
mutex_m (0.3.0)
|
39
44
|
parallel (1.26.3)
|
40
|
-
parser (3.3.
|
45
|
+
parser (3.3.6.0)
|
41
46
|
ast (~> 2.4.1)
|
42
47
|
racc
|
43
|
-
pry (0.
|
48
|
+
pry (0.15.2)
|
44
49
|
coderay (~> 1.1)
|
45
50
|
method_source (~> 1.0)
|
46
51
|
racc (1.8.1)
|
47
|
-
rack (3.1.
|
52
|
+
rack (3.1.8)
|
48
53
|
rainbow (3.1.1)
|
49
54
|
rake (13.2.1)
|
50
|
-
regexp_parser (2.
|
51
|
-
rexml (3.3.7)
|
55
|
+
regexp_parser (2.10.0)
|
52
56
|
rspec (3.13.0)
|
53
57
|
rspec-core (~> 3.13.0)
|
54
58
|
rspec-expectations (~> 3.13.0)
|
55
59
|
rspec-mocks (~> 3.13.0)
|
56
|
-
rspec-core (3.13.
|
60
|
+
rspec-core (3.13.2)
|
57
61
|
rspec-support (~> 3.13.0)
|
58
62
|
rspec-expectations (3.13.3)
|
59
63
|
diff-lcs (>= 1.2.0, < 2.0)
|
60
64
|
rspec-support (~> 3.13.0)
|
61
|
-
rspec-mocks (3.13.
|
65
|
+
rspec-mocks (3.13.2)
|
62
66
|
diff-lcs (>= 1.2.0, < 2.0)
|
63
67
|
rspec-support (~> 3.13.0)
|
64
|
-
rspec-support (3.13.
|
65
|
-
rubocop (1.
|
68
|
+
rspec-support (3.13.2)
|
69
|
+
rubocop (1.69.2)
|
66
70
|
json (~> 2.3)
|
67
71
|
language_server-protocol (>= 3.17.0)
|
68
72
|
parallel (~> 1.10)
|
69
73
|
parser (>= 3.3.0.2)
|
70
74
|
rainbow (>= 2.2.2, < 4.0)
|
71
|
-
regexp_parser (>=
|
72
|
-
|
73
|
-
rubocop-ast (>= 1.31.1, < 2.0)
|
75
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
76
|
+
rubocop-ast (>= 1.36.2, < 2.0)
|
74
77
|
ruby-progressbar (~> 1.7)
|
75
|
-
unicode-display_width (>= 2.4.0, <
|
76
|
-
rubocop-ast (1.
|
78
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
79
|
+
rubocop-ast (1.37.0)
|
77
80
|
parser (>= 3.3.1.0)
|
78
|
-
rubocop-
|
79
|
-
rubocop (~> 1.
|
80
|
-
|
81
|
-
rubocop (~> 1.
|
82
|
-
rubocop-
|
83
|
-
rubocop-rails (~> 2.24.0)
|
81
|
+
rubocop-config-umbrellio (1.69.0.101)
|
82
|
+
rubocop (~> 1.69.0)
|
83
|
+
rubocop-factory_bot (~> 2.26.0)
|
84
|
+
rubocop-performance (~> 1.23.0)
|
85
|
+
rubocop-rails (~> 2.28.0)
|
84
86
|
rubocop-rake (~> 0.6.0)
|
85
|
-
rubocop-rspec (~>
|
86
|
-
rubocop-sequel (~> 0.3.
|
87
|
+
rubocop-rspec (~> 3.3.0)
|
88
|
+
rubocop-sequel (~> 0.3.0)
|
87
89
|
rubocop-factory_bot (2.26.1)
|
88
90
|
rubocop (~> 1.61)
|
89
|
-
rubocop-performance (1.
|
91
|
+
rubocop-performance (1.23.1)
|
90
92
|
rubocop (>= 1.48.1, < 2.0)
|
91
93
|
rubocop-ast (>= 1.31.1, < 2.0)
|
92
|
-
rubocop-rails (2.
|
94
|
+
rubocop-rails (2.28.0)
|
93
95
|
activesupport (>= 4.2.0)
|
94
96
|
rack (>= 1.1)
|
95
|
-
rubocop (>= 1.
|
97
|
+
rubocop (>= 1.52.0, < 2.0)
|
96
98
|
rubocop-ast (>= 1.31.1, < 2.0)
|
97
99
|
rubocop-rake (0.6.0)
|
98
100
|
rubocop (~> 1.0)
|
99
|
-
rubocop-rspec (
|
100
|
-
rubocop (~> 1.40)
|
101
|
-
rubocop-capybara (~> 2.17)
|
102
|
-
rubocop-factory_bot (~> 2.22)
|
103
|
-
rubocop-rspec_rails (~> 2.28)
|
104
|
-
rubocop-rspec_rails (2.29.1)
|
101
|
+
rubocop-rspec (3.3.0)
|
105
102
|
rubocop (~> 1.61)
|
106
|
-
rubocop-sequel (0.3.
|
103
|
+
rubocop-sequel (0.3.8)
|
107
104
|
rubocop (~> 1.0)
|
108
105
|
ruby-progressbar (1.13.0)
|
106
|
+
securerandom (0.3.2)
|
109
107
|
simplecov (0.22.0)
|
110
108
|
docile (~> 1.1)
|
111
109
|
simplecov-html (~> 0.11)
|
@@ -115,7 +113,9 @@ GEM
|
|
115
113
|
simplecov_json_formatter (0.1.4)
|
116
114
|
tzinfo (2.0.6)
|
117
115
|
concurrent-ruby (~> 1.0)
|
118
|
-
unicode-display_width (
|
116
|
+
unicode-display_width (3.1.3)
|
117
|
+
unicode-emoji (~> 4.0, >= 4.0.4)
|
118
|
+
unicode-emoji (4.0.4)
|
119
119
|
|
120
120
|
PLATFORMS
|
121
121
|
ruby
|
@@ -134,4 +134,4 @@ DEPENDENCIES
|
|
134
134
|
simplecov-lcov
|
135
135
|
|
136
136
|
BUNDLED WITH
|
137
|
-
2.
|
137
|
+
2.5.23
|
data/README.md
CHANGED
@@ -190,6 +190,36 @@ a.memoized?(:call) # => true
|
|
190
190
|
a.memoized?(:execute) # => false
|
191
191
|
```
|
192
192
|
|
193
|
+
### Marshal-compatible Memoization
|
194
|
+
|
195
|
+
In order for objects to be marshaled and loaded in a different Ruby process,
|
196
|
+
hashed arguments must be disabled in order for memoized values to be retained.
|
197
|
+
Note that this can have a performance impact if the memoized method contains
|
198
|
+
arguments.
|
199
|
+
|
200
|
+
```ruby
|
201
|
+
Memery.use_hashed_arguments = false
|
202
|
+
|
203
|
+
class A
|
204
|
+
include Memery
|
205
|
+
|
206
|
+
memoize def call
|
207
|
+
puts "calculating"
|
208
|
+
42
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
a = A.new
|
213
|
+
a.call
|
214
|
+
|
215
|
+
Marshal.dump(a)
|
216
|
+
# => "\x04\bo:\x06A\x06:\x1D@_memery_memoized_values{\x06:\tcallS:3Memery::ClassMethods::MemoizationModule::Cache\a:\vresulti/:\ttimef\x14663237.14822323"
|
217
|
+
|
218
|
+
# ...in another Ruby process:
|
219
|
+
a = Marshal.load("\x04\bo:\x06A\x06:\x1D@_memery_memoized_values{\x06:\tcallS:3Memery::ClassMethods::MemoizationModule::Cache\a:\vresulti/:\ttimef\x14663237.14822323")
|
220
|
+
a.call # => 42
|
221
|
+
```
|
222
|
+
|
193
223
|
## Differences from Other Gems
|
194
224
|
|
195
225
|
Memery is similar to [Memoist](https://github.com/matthewrudy/memoist), but it doesn't override methods. Instead, it uses Ruby 2's `Module.prepend` feature. This approach is cleaner, allowing you to inspect the original method body with `method(:x).super_method.source`, and it ensures that subclasses' methods function properly. If you redefine a memoized method in a subclass, it won't be memoized by default. You can memoize it normally without needing an awkward `identifier: ` argument, and it will just work:
|
data/benchmark.rb
CHANGED
@@ -32,6 +32,10 @@ class Foo
|
|
32
32
|
memoize def find_new(char)
|
33
33
|
base_find(char)
|
34
34
|
end
|
35
|
+
|
36
|
+
memoize def find_optional(*)
|
37
|
+
base_find("z")
|
38
|
+
end
|
35
39
|
end
|
36
40
|
end
|
37
41
|
|
@@ -43,6 +47,10 @@ def test_with_args
|
|
43
47
|
Foo.find_new("d")
|
44
48
|
end
|
45
49
|
|
50
|
+
def test_empty_args
|
51
|
+
Foo.find_optional
|
52
|
+
end
|
53
|
+
|
46
54
|
Benchmark.ips do |x|
|
47
55
|
x.report("test_no_args") { test_no_args }
|
48
56
|
end
|
@@ -51,6 +59,14 @@ Benchmark.memory do |x|
|
|
51
59
|
x.report("test_no_args") { 100.times { test_no_args } }
|
52
60
|
end
|
53
61
|
|
62
|
+
Benchmark.ips do |x|
|
63
|
+
x.report("test_empty_args") { test_empty_args }
|
64
|
+
end
|
65
|
+
|
66
|
+
Benchmark.memory do |x|
|
67
|
+
x.report("test_empty_args") { 100.times { test_empty_args } }
|
68
|
+
end
|
69
|
+
|
54
70
|
Benchmark.ips do |x|
|
55
71
|
x.report("test_with_args") { test_with_args }
|
56
72
|
end
|
@@ -59,4 +75,14 @@ Benchmark.memory do |x|
|
|
59
75
|
x.report("test_with_args") { 100.times { test_with_args } }
|
60
76
|
end
|
61
77
|
|
78
|
+
Memery.use_hashed_arguments = false
|
79
|
+
Benchmark.ips do |x|
|
80
|
+
x.report("test_with_args_no_hash") { test_with_args }
|
81
|
+
end
|
82
|
+
|
83
|
+
Benchmark.memory do |x|
|
84
|
+
x.report("test_with_args_no_hash") { 100.times { test_with_args } }
|
85
|
+
end
|
86
|
+
Memery.use_hashed_arguments = true
|
87
|
+
|
62
88
|
puts "```"
|
data/lib/memery/version.rb
CHANGED
data/lib/memery.rb
CHANGED
@@ -4,11 +4,15 @@ require "memery/version"
|
|
4
4
|
|
5
5
|
module Memery
|
6
6
|
class << self
|
7
|
+
attr_accessor :use_hashed_arguments
|
8
|
+
|
7
9
|
def monotonic_clock
|
8
10
|
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
9
11
|
end
|
10
12
|
end
|
11
13
|
|
14
|
+
@use_hashed_arguments = true
|
15
|
+
|
12
16
|
OUR_BLOCK = lambda do
|
13
17
|
extend(ClassMethods)
|
14
18
|
include(InstanceMethods)
|
@@ -68,11 +72,12 @@ module Memery
|
|
68
72
|
end
|
69
73
|
end
|
70
74
|
|
75
|
+
# rubocop:disable Metrics/MethodLength
|
71
76
|
def define_memoized_method!(klass, method_name, condition: nil, ttl: nil)
|
72
|
-
|
73
|
-
|
77
|
+
# Include a suffix in the method key to differentiate between methods of the same name
|
78
|
+
# being memoized throughout a class inheritance hierarchy
|
79
|
+
method_key = "#{method_name}_#{klass.name || object_id}"
|
74
80
|
original_visibility = method_visibility(klass, method_name)
|
75
|
-
original_arity = klass.instance_method(method_name).arity
|
76
81
|
|
77
82
|
define_method(method_name) do |*args, &block|
|
78
83
|
if block || (condition && !instance_exec(&condition))
|
@@ -80,7 +85,12 @@ module Memery
|
|
80
85
|
end
|
81
86
|
|
82
87
|
cache_store = (@_memery_memoized_values ||= {})
|
83
|
-
cache_key =
|
88
|
+
cache_key = if args.empty?
|
89
|
+
method_key
|
90
|
+
else
|
91
|
+
key_parts = [method_key, *args]
|
92
|
+
Memery.use_hashed_arguments ? key_parts.hash : key_parts
|
93
|
+
end
|
84
94
|
cache = cache_store[cache_key]
|
85
95
|
|
86
96
|
return cache.result if cache&.fresh?(ttl)
|
@@ -95,6 +105,7 @@ module Memery
|
|
95
105
|
ruby2_keywords(method_name)
|
96
106
|
send(original_visibility, method_name)
|
97
107
|
end
|
108
|
+
# rubocop:enable Metrics/MethodLength
|
98
109
|
|
99
110
|
private
|
100
111
|
|
data/memery.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: memery
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yuri Smirnov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-03-04 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Memery is a gem for memoization.
|
14
14
|
email:
|
@@ -43,14 +43,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
43
43
|
requirements:
|
44
44
|
- - ">="
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version:
|
46
|
+
version: 3.0.0
|
47
47
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
48
|
requirements:
|
49
49
|
- - ">="
|
50
50
|
- !ruby/object:Gem::Version
|
51
51
|
version: '0'
|
52
52
|
requirements: []
|
53
|
-
rubygems_version: 3.
|
53
|
+
rubygems_version: 3.5.23
|
54
54
|
signing_key:
|
55
55
|
specification_version: 4
|
56
56
|
summary: A gem for memoization.
|