2016-01-18 42 views
3

Ruby是否會緩存方法的結果,以便在調用兩次時不需要對它進行兩次評估?Ruby會緩存將評估爲相同結果的方法的結果嗎?

我在Rails的工作,因此,例如,我可以做到以下幾點在哪裏存儲傳遞到Rails控制器中的一個變量,像這樣一個參數的時結果:

def foo_bar_method 
    case param[:foobar] 
    when 'foo' then 'bar' 
    when 'bar' then 'baz' 
    else 'barbaz' 
end 

result = foo_bar_method 
puts result 
puts result 

這樣,我只評估foo_bar_method一次。 Ruby會緩存此方法的結果(還是Rails會這樣做)?使用上面顯示的代碼會更快嗎,還是下面的代碼會導致相同的性能?

def foo_bar_method 
    case param[:foobar] 
    when 'foo' then 'bar' 
    when 'bar' then 'baz' 
    else 'barbaz' 
end 

puts foo_bar_method 
puts foo_bar_method 
+0

它會緩存SQL查詢,但我不認爲上述方法的結果將被緩存。 – errata

+0

注意:爲了做到這一點,Ruby必須確定該方法是否引用透明,這相當於解決停機問題。 –

回答

1

Ruby沒有緩存方法的結果,因爲幾乎沒有任何紅寶石功能可以被稱爲純函數,編譯器就無法知道該值由於紅寶石變得如地獄般變化或不變。例如,此功能:

def four 
    2 + 2 
end 

可能似乎在時間上不變。好吧,不,如果你這樣做:

class Fixnum 
    def +(other) 
    self * other - 3 
    end 
end 

那麼,顯然這樣做可能是你可以做的最糟糕的事情,但事實是,你可以做到這一點。

在你的兩個例子中,沒有可衡量的性能增益,但是在很多情況下,它是編寫代碼的標準方式(執行一次並存儲到變量中)。

當你確定你是在處理一個函數,將總是產生相同的結果,你可以使用實例變量這樣它緩存:

def foo_bar_method 
    @foo_bar_method ||= 
    case param[:foobar] 
     when 'foo' then 'bar' 
     when 'bar' then 'baz' 
     else 'barbaz' 
    end 
end 

假設這是在你的控制器的方法,它是安全的假設這個值在控制器生命週期中不會改變(因爲每個請求使用不同的控制器實例),所以緩存可能會有一些意義,特別是對於較重的計算。

1

Ruby不會緩存方法的結果。如果你想自己做,你可以自己添加記憶。有很多方法可以做到這一點和幾個寶石。只是取決於你所需要的(即參數處理等)

https://en.wikipedia.org/wiki/Memoization