2011-05-30 81 views
2

我拉着我的頭髮試圖優化我的一個控制器動作。我遇到了一個非常奇怪的問題,如果我將自定義選項傳遞給我的as_json方法,它似乎會減慢序列化。以下是比較基準。 @location是一個包含大約60個ActiveRecord對象的數組。JSON序列化性能Enigma

x.report("as_json") do 
    @location.as_json(:methods => [:nearby_categories]) 
end 

x.report("js user") do 
    @json = @locations.as_json(
    :user_data => {:favorites => [], :rank_rewards => []}, 
    :methods => [:nearby_categories]) 
end 

這裏的區別是:

as_json 0.000000 0.000000 0.000000 ( 0.000031) 
js user 1.320000 0.060000 1.380000 ( 1.390047) 

我已經overidden的serializable_hash方法上我的位置模型:

def serializable_hash(options = {}) 
    only = %w(address business_id city franchise_name id lat lng phone rating state total_reviews zip) 
    options ||= {} 
    options[:only] ||= only.map(&:to_sym) 
    hash = super(:only => options[:only], :except => options[:except], :methods => options[:methods]) 

# ... 
# omitted code which sets additional attributes 
# ... 

if options && (data = options[:user_data]) 
    fav = 
    if data && favs = data[:favorites] 
    favs.select { |f| f.location_id == self.id }.first 
    else 
    user.favorites.find_by_location_id(self.id) 
    end 
    hash["favorite_id"] = fav ? fav.id : nil 

    if data && ranks = data[:rank_rewards] 
    if rank = ranks.select {|urr| urr.location_id == self.id }.first 
     hash["user_rank_level"] = {:name => rank.rank_reward_level.name, :user_rank_reward_id => rank.id} 
    end 
    else 
    hash["user_rank_level"] = self.user_rank(user) 
    end 
end 

hash 
end 

現在通過在兩個空數組應該不會對此有什麼影響代碼,只是爲了使雙重確保我試着傳遞一個選項,我不處理:

x.report("js user") do 
    @json = @locations.as_json(
    :garbage => {}, 
    :methods => [:nearby_categories]) 
end 

我也得到相同的結果:

js user 1.230000 0.070000 1.300000 ( 1.295439) 

我還沒有傳遞任何非標準選項超。這怎麼可能發生?

+1

如果您正確鍵入第一個代碼段,它將使用@location和第二個@locations。你在序列化同一個對象嗎? – 2011-05-30 20:13:21

+0

史蒂夫,史蒂夫,史蒂夫,你搖滾。那是一條巨大的紅鯡魚。如果我修正了我的錯字,「as_json」步驟需要1.3秒,「js用戶」步驟會持續很短的時間。所以它必須將AR對象加載到內存中,並且首先需要花費時間。 – 2011-05-31 01:47:34

回答

0

找到這種問題的一種方法是測量各種片段。

另一種方法是將其陷入行爲。 如果您使用rdb debugger您可以隨機暫停它並說其中顯示堆棧。 成本越高,抓住它的機會就越好。

做幾次。 您在多個堆棧示例中看到的任何代碼行(如果可以對其進行優化)都將節省大量時間。 這就是random-pause技術。 Here's an example,這恰好在python中,但可以在任何語言中使用。