Ruby memory, efficiency

This question mainly concerns the internal elements of Ruby, speed can be estimated by a simple standard.

What is the most efficient way to memoize the return value in ruby?

I always remembered the values ​​with:

def method @value ||= calculate_value end 

But since it technically expands to:

 @value = @value || calculate_value 

I wonder about the effectiveness of re-executing the same task every time.

Would it be better?

 def method @value ? @value : (@value = calculate_value) end 

Also, does it change in different interpreters? MRI, Rubinius, etc.

+7
ruby memoization
source share
3 answers

Your example

 @value ||= calculate_value 

equivalently

 @value || @value = calculate_value 

and not equivalent

 @value = @value || calculate_value 

Therefore, the answer is: it is very effective. It does not reinstall every time.

+6
source share

@spickermann, @tompave, sorry to send it as an answer, but I need code formatting to post test results for different cases. It seems like the explicit way is the fastest @a || @a = calculated_value @a || @a = calculated_value

 > n = 10000000; > a = 1; > puts Benchmark.measure { n.times { a ||= 1 } } 0.570000 0.000000 0.570000 ( 0.569977) > puts Benchmark.measure { n.times { a ? a : a = 1 } } 0.560000 0.000000 0.560000 ( 0.562855) > puts Benchmark.measure { n.times { a || a = 1 } } 0.530000 0.000000 0.530000 ( 0.532715) > @a = 1; > puts Benchmark.measure { n.times { @a ||= 1 } } 0.870000 0.000000 0.870000 ( 0.869489) > puts Benchmark.measure { n.times { @a ? @a : @a = 1 } } 0.670000 0.000000 0.670000 ( 0.668910) > puts Benchmark.measure { n.times { @a || @a = 1 } } 0.610000 0.000000 0.610000 ( 0.613978) 

ruby 2.1.2p95 (version 2014-05-08 45877) [x86_64-darwin13.0]

All 3 notations behave the same in terms of results, however, the last one is the voice in terms of performance. Unfortunately, all of this is empirical, and I cannot link any ruby ​​source code here.

0
source share

I think that any differences between ||= and ... = ... || ... ... = ... || ... should be thin.

Perhaps a much more efficient way is to switch the method when the value is set. This switch happens only once, and from there the method call becomes just a reference to the variable, so it should be fast, and the advantage increases as the number of times the method is called increases.

 def method alias method memoized_value @value ||= calculate_value end def memoized_value; @value end 

This assumes that calculate_value always returns a plausible value, and there is no other part in the code that modifies the value, so that after calling method value of the variable remains true.

0
source share

All Articles