【问题标题】:Performances on rails铁轨上的表演
【发布时间】:2011-12-06 19:02:24
【问题描述】:

我对导轨的性能有疑问。当我像这样对控制器进行 ajax 调用时:

def test
    @hotels = Hotel.all
    render :json => ['hotels' => @hotels ], :include=> [:country, :city]
end

完成可能需要 2-5 秒。我的数据库中只有 40 家酒店。我认为它很长......例如,Django上的相同请求将需要400ms

我是不是忘了配置好我的环境?

我使用 Rails 企业版和乘客版。

编辑:我的日志文件:

     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)

它的写入时间为 405 毫秒,但 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

感谢您的帮助。

【问题讨论】:

  • 你能看到控制台输出或日志文件告诉你什么吗?数据库、渲染等花费了多少时间?
  • 这是在开发还是生产中?您在日志中看到了哪些查询?您的酒店、国家和城市协会是如何建立的?
  • @Sebastien 你肯定遇到了我建议的 N+1 问题。如果您按照我的建议进行更改,您最终会在该文件中得到 3 个 SQL 行
  • 我用的是开发环境。
  • @Sebastien,我建议你也看看网络时间。看起来这没有在您的本地计算机上运行。 3 秒包括延迟、响应时间和传输时间。返回的json有多大kb?

标签: ruby-on-rails ruby


【解决方案1】:

我正在使用 VMWare 使我的 Web 服务器运行。我的表演问题与此有关。我在这里找到我的解决方案:

Webrick is very slow to respond. How to speed it up?

【讨论】:

    【解决方案2】:

    查看日志,Rails 似乎认为它在 405 毫秒内得到了响应。这让堆栈的其余部分需要考虑:

    1. 导轨 (✓)
    2. 乘客
    3. 阿帕奇
    4. 网络
    5. DNS 解析
    6. 浏览器渲染

    首先,看看其他浏览器的表现如何。我在我们的一个(非 Rails)网站上看到偶尔出现问题,使用 Firefox,而基于 Webkit 的浏览器(Safari、Chrome)还可以。也许 Firefox 出于某种原因(例如 DNS resolving issues 或其他)阻塞了。

    如果所有浏览器都相同(或者特别是如果 Firefox 是罪魁祸首),那么打开 Firebug 并查看Net 标签,尤其是其下的 XHR (AJAX) 标签。将鼠标悬停在其中一个查询的时间栏上可查看时间的细分:DNS、连接、发送、等待、接收。

    如果 Firebug 表明时间花在请求本身上(发送、等待、接收),那么看看 Apache 日志 - 打开 CustomLog 时间报告(添加 %D - see documentation)并查看Apache 认为这些请求需要多长时间。

    这应该会缩小您的问题范围以进一步分析原因。

    【讨论】:

      【解决方案3】:

      看看你的代码,我猜你有一个简单的“N+1”问题。

      即您将@hotels 加载到一个数组中,但是当您来生成json 你加载country和cityfor eachhotel。

      因此,对于您的 40 家酒店,您总共需要进行 81 次数据库查询。

      这可以通过在加载时执行include 来改进。

      老式风格

      Hotel.all(:include => [:country, :city])
      

      Rails 3 风格

      Hotel.includes(:country, :city).all
      

      通过此更改,您总共应该只进行 3 次数据库调用。

      有关详细信息,请参阅 Eager Loading 上的 Rails 指南。

      【讨论】:

      • 我尝试过,但它不会改变我的请求时间。
      猜你喜欢
      • 2016-09-25
      • 1970-01-01
      • 2013-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多