【发布时间】:2011-05-30 19:42:48
【问题描述】:
我正在努力优化我的控制器操作之一。我遇到了一个非常奇怪的问题,如果我将自定义选项传递给我的 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。怎么会这样?
【问题讨论】:
-
如果您正确键入了第一个代码 sn-p,它将使用@location 和第二个@locations。你是在序列化同一个对象吗?
-
史蒂夫,史蒂夫,史蒂夫,你摇滚。这引起了巨大的红鲱鱼。如果我修正了我的错字,“as_json”步骤需要 1.3 秒,而“js 用户”步骤只需要很短的时间。所以它必须将 AR 对象加载到内存中,并且首先需要它们的任何东西都需要时间。
标签: ruby-on-rails performance json