JSON序列化性能之谜

时间:2011-05-30 19:42:48

标签: ruby-on-rails performance json

我正在试着优化我的一个控制器动作。我遇到了一个非常奇怪的问题,如果我将自定义选项传递给我的as_json方法,它似乎会减慢序列化速度。以下是比较基准。 @location是一个包含大约60个位置ActiveRecord对象的数组。

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)

我在我的位置模型上覆盖了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)

我甚至没有将任何非标准选项传递给super。怎么会发生这种情况?

1 个答案:

答案 0 :(得分:0)

找到这种问题的一种方法是测量各种部分。

另一种方法是将其陷入行为中。 如果你使用rdb debugger,你可以随意暂停它并说 where 来显示堆栈。 花费的时间越多,抓住它的机会就越大。

多次这样做。 您在多个堆栈样本上看到的任何代码行,如果您可以优化它,将节省大量时间。 这是random-pause技术。 Here's an example,恰好在python中,但可以使用任何语言。