Nuby Tip for the Day : Memoization

J

John Carter

So you have written your ruby app.

It works.

So you throw it at a really Big Problem....and it grinds to a
halt. Too slow, too much memory.

If I find I that keep recreating an object, here is a trick that I
sometimes play...

Replace...
-------------
class BigExpensiveMadeOften
def initialize( unique_name)
# Big expensive computation
end
end
 
J

Joel VanderWerf

Just a little correction to a worthy post...

John Carter wrote:
...
class BigExpensiveMadeOften
def initialize( unique_name)
# Big expensive computation
end

@@memo = Hash.new {|hash,key|
result = BigExpensiveMadeOften.new( unique_name)
^^^^^^^^^^^
should be "key"
 
J

John Carter

Just a little correction to a worthy post...
thanks

John Carter wrote:
...

make that
@@memo = Hash.new {|hash,key| hash[key] = BigExpensiveMadeOften.new( key)}


Reminder for the day for not so Nubies...

Every reference to a string is a String.new, so sometimes factoring out string constants out of inner loops can be a big win...


(1..1000).each do |i|
if (i % 2) == 0
a << 'Was even'
else
a << 'Was odd'
end


Creates 500 indentical instances of 'Was even' and 500 identical instances of 'Was odd'

EVEN_MSG = 'Was even'
ODD_MSG = 'Was odd'

(1..1000).each do |i|
if (i % 2) == 0
a << EVEN_MSG
else
a << ODD_MSG
end


Saves you 998 strings



=======foo.rb==========
a=[]
(1..1000).each do |i|
a << 'This is a great big string'
end

p a[100]
a[100][0] = 32


p a[99]
p a[100]
p a[101]

b = "This is an long string"

a=[]
(1..1000).each do |i|
a << b
end

p a[100]
a[100][0] = 32


p a[99]
p a[100]
p a[101]
====================
ruby -w foo.rb
"This is a great big string"
"This is a great big string"
" his is a great big string"
"This is a great big string"
"This is an long string"
" his is an long string"
" his is an long string"
" his is an long string"




John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : (e-mail address removed)
New Zealand

The universe is absolutely plastered with the dashed lines exactly one
space long.
 
F

Florian Frank

Really an easy optimization to do.

Yep. You could also make it transparent for the clients of your class:

class BigExpensiveMadeOften
def initialize(unique_name)
# Big expensive computation
end

@@memo = Hash.new { |hash,key|
result = BigExpensiveMadeOften.allocate
result.__send__:)initialize, key)
hash[key] = result
}

def BigExpensiveMadeOften.new(unique_name)
@@memo[unique_name]
end
end

foo = BigExpensiveMadeOften.new('foo')
bar = BigExpensiveMadeOften.new('bar')
p foo
p bar
foo = BigExpensiveMadeOften.new('foo')
p foo
 
B

Brian Mitchell

Just a little correction to a worthy post...
thanks

John Carter wrote:
...

make that
@@memo = Hash.new {|hash,key| hash[key] = BigExpensiveMadeOften.new( key)}

Reminder for the day for not so Nubies...

Every reference to a string is a String.new, so sometimes factoring out string constants out of inner loops can be a big win...

Possibly you meant a string literal. A reference is what the variable
ends up holding.

Brian Mitchell
 
G

gabriele renzi

Florian Frank ha scritto:
Yep. You could also make it transparent for the clients of your class:

and you can write your own memoize() method or Memoized class, to
transform a method/class into what you want transparently
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,160
Messages
2,570,889
Members
47,422
Latest member
LatashiaZc

Latest Threads

Top