我对rails的性能有一个问题。当我像这样对控制器进行ajax调用时:
def test
@hotels = Hotel.all
render :json => ['hotels' => @hotels ], :include=> [:country, :city]
end
可能需要2-5秒才能完成。我的数据库里只有40家酒店。我觉得它很长...例如,Django上的相同请求将需要400ms
我忘记配置好我的环境了吗?
我使用的是Rails企业版和passenger。
编辑:我的日志文件:
Started GET "/hotels/test.json" for 172.16.81.1 at Wed Oct 12 22:11:06 +0200 2011
[paperclip] Duplicate URL for image with /system/:attachment/:id/:style/:filename. This will clash with attachment defined in HotelImage class
[paperclip] Duplicate URL for thumbnail with /system/:attachment/:id/:style/:filename. This will clash with attachment defined in Hotel class
[paperclip] Duplicate URL for map with /system/:attachment/:id/:style/:filename. This will clash with attachment defined in Hotel class
[paperclip] Duplicate URL for thumbnail with /system/:attachment/:id/:style/:filename. This will clash with attachment defined in DestinationAlbumPhoto class
[paperclip] Duplicate URL for map with /system/:attachment/:id/:style/:filename. This will clash with attachment defined in Destination class
[paperclip] Duplicate URL for image with /system/:attachment/:id/:style/:filename. This will clash with attachment defined in Continent class
[paperclip] Duplicate URL for thumbnail with /system/:attachment/:id/:style/:filename. This will clash with attachment defined in Destination class
[paperclip] Duplicate URL for image with /system/:attachment/:id/:style/:filename. This will clash with attachment defined in Event class
[paperclip] Duplicate URL for thumbnail with /system/:attachment/:id/:style/:filename. This will clash with attachment defined in HotelAlbumPhoto class
[paperclip] Duplicate URL for map with /system/:attachment/:id/:style/:filename. This will clash with attachment defined in Event class
Processing by HotelController#test as JSON
[1m[36mHotel Load (0.2ms)[0m [1mSELECT `hotels`.* FROM `hotels`[0m
[1m[35mCountry Load (0.1ms)[0m SELECT `countries`.* FROM `countries` WHERE (`countries`.`id` = 3)
[1m[36mCity Load (0.1ms)[0m [1mSELECT `cities`.* FROM `cities` WHERE (`cities`.`id` = 2)[0m
Completed 200 OK in 405ms (Views: 366.1ms | ActiveRecord: 0.3ms)
它写的是405ms,但firefox告诉我是3.7秒。
我的酒店模式:
class Hotel < ActiveRecord::Base
cattr_reader :per_page
@@per_page = 16
belongs_to :hotel_type
belongs_to :hotel_theme
belongs_to :country
belongs_to :city
belongs_to :destination
belongs_to :continent
has_many :hotel_comments, :dependent => :destroy
has_many :hotel_album_photos, :dependent => :destroy
has_many :hotel_activity_values
has_many :hotel_service_values
accepts_nested_attributes_for :hotel_album_photos
has_attached_file :thumbnail, :styles => { :medium => "300x300>", :thumb => "191x134>"} , :default_url => '/images/default/missing.png'
has_attached_file :map, :styles => { :medium => "300x300>", :thumb => "191x134>"} , :default_url => '/images/default/missing.png'
scope :country, lambda { |country_id|
self.scoped.where('country_id IN ( ? )', country_id) unless country_id.blank?
}
scope :selection, lambda { |selection|
self.scoped.where('selection = ? ', 1) unless selection.blank?
}
scope :city, lambda { |city_id|
self.scoped.where('city_id IN ( ? )', city_id) unless city_id.blank?
}
scope :hoteltype, lambda { |type|
self.scoped.where('hotel_type_id IN ( ? )', type) unless type.blank?
}
scope :theme, lambda { |theme|
self.scoped.where('hotel_theme_id IN ( ? )', theme) unless theme.blank?
}
scope :prices, lambda { |prices|
condition = []
prices.each do |price|
pricesArray = price.split('-')
condition.push '(price BETWEEN ' + pricesArray[0] + ' AND ' + pricesArray[1] + ')'
end
self.scoped.where(condition.join(' OR '))
}
scope :order_by_price, lambda { |direction|
self.scoped.order('price ' + direction)
}
scope :order_by_rate, lambda { |rate|
self.scoped.order('global_rate ' + rate)
}
scope :services, lambda { |services|
{:joins => [:hotel_service_values ] , :conditions => { :hotel_service_values => {:hotel_service_id => services}}}
}
scope :limiter, lambda { |limiter|
self.scoped.limit(limiter)
}
end
谢谢你的帮助。
发布于 2011-10-14 15:56:08
我正在使用VMWare让我的web服务器运行。我的表现问题就在于此。我在这里找到了我的解决方案:
发布于 2011-10-13 17:20:06
看看你的代码,我猜你有一个简单的"N+1“问题。
也就是说,您将@hotels
加载到一个数组中,但是当您要生成json时,您需要加载country
和cityfor each
酒店。
因此,对于您的40家酒店,您总共需要执行81次数据库查询。
这可以通过在加载时执行include
来简单地改进。
在旧风格中
Hotel.all(:include => [:country, :city])
在Rails 3风格中
Hotel.includes(:country, :city).all
使用此更改,您总共应该只进行3次数据库调用。
有关更多信息,请参阅Eager Loading上的Rails指南。
发布于 2011-10-13 21:24:02
看一下日志,Rails似乎认为它在405毫秒内就得到了响应。这使得堆栈的其余部分需要考虑:
首先,看看其他浏览器的表现如何。我偶尔会在我们的一个(非rails)网站上看到Firefox的问题,而基于Webkit的浏览器(Safari,Chrome)是可以的。也许火狐因为某些原因(例如DNS resolving issues或其他原因)而卡住了。
如果所有浏览器都是相同的(尤其是,如果Firefox是罪魁祸首),那么打开Firebug并查看Net
选项卡,特别是它下面的XHR (AJAX)选项卡。将鼠标悬停在其中一个查询的时间栏上,可以看到时间流逝的细目: DNS、连接、发送、等待、接收。
如果Firebug指示时间花在请求本身上(发送、等待、接收),那么查看Apache日志-打开CustomLog
时间报告(添加%D
- see documentation),看看Apache认为这些请求需要多长时间。
这将缩小您的问题范围,以便进一步分析原因。
https://stackoverflow.com/questions/7751713
复制相似问题