[英]Rails Memoization of Helper method
我有一個輔助方法,該方法執行昂貴的計算並返回Hash
,並且該Hash在我的整個應用程序生命周期中都是恆定的(這意味着它只能在重新部署后才能更改),並且也不接受任何參數。
為了提高性能,我希望可以“緩存”生成的Hash
。
我不想用Rails緩存對於這一點,因為我想避免額外的行程Memcached和我不想要的反序列串入一個散列的開銷。
我的第一個想法是將結果哈希分配給Constant並在其上調用.freeze
。 但是幫助程序是一個實例方法,常量始終存在於類中,我不得不執行以下超級hacky解決方案:
module FooHelper
def expensive_calculation_method
resulting_hash
end
EXPENSIVE_CALCULATION_CONSTANT = Class.new.extend(self).expensive_calculation_method.freeze
這是由於helper方法是實例方法,helper是Module(導致偽類擴展,所以我可以調用實例方法),並且我還必須在實例方法之后聲明常量AFTER(如果我正確聲明的話)在module FooHelper
,我得到了一個undefined method 'expensive_calculation_method'
。
第二個想法是使用記憶,但是至少對於Rails Controller來說,記憶是在單個請求的生命周期內變量的持久性,因此僅當您在單個請求中多次重復使用變量時才有價值,這不是我的想法。情況,但同時Helpers是模塊,而不是要實例化的類,並且到目前為止,我不知道該怎么做。
我將如何緩存該哈希,或以對請求的持久化方式對其進行記憶?
如果要在啟動時緩存某些痛苦的操作的結果,請執行以下操作:
module MyExpensiveOperation
COMPUTED_RESULT = OtherModule.expensive_operation
def self.cached
COMPUTED_RESULT
end
end
只需確保以某種方式加載了該模塊,否則該模塊將不會啟動。 您始終可以在environment.rb
或作為config/initializer
類型文件強制require
該模塊。
如果要延遲加載,其基本原理是相同的:
module MyExpensiveOperation
def self.cached
return @cached if (defined?(@cached))
@cached = OtherModule.expensive_operation
end
end
這將處理由於任何原因返回nil
或false
。 它將運行一次,並且只能運行一次,除非您有多個線程同時觸發它。 如果是這種情況,則可以通過自動鎖定來使您的模塊並發感知。
根據您的評論,這只會在應用程序啟動時發生變化,因此將其放在初始化程序中就可以解決問題。
# config/initializers/expensive_thing.rb
$EXENSIVE_THING_GLOBAL = expensive_calculation
# or
EXPENSIVE_THING_CONSTANT = expensive_calculation
# or
Rails.application.config.expensive_thing = expensive_calcualatioin
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.