Ruby On Rails很慢……?

我正在编写一个Web应用程序来监控家具厂的生产流程。 它有数千个数据需要处理。 到目前为止,我在Mongrel + MySQL上运行RoR并且它真的很慢(对于某些视图来说是2-4分钟)。 当我查看RoR日志时,似乎数据库查询不是很慢(0-10ms)。

RoR在将​​数据库数据转换为对象时是否会变慢? 杂种慢吗?

编辑 :第一件事:我在开发中。 ENV。 在生产环境中,最慢的视图需要2分钟(在好的计算机上会减少不到1分钟,我的是5年)。 有了ruby-prof和一些常识,我发现哪些方法正在减慢应用程序的速度。 问题是在大型数据集的循环中调用单个SQL查询:

ofs = Ofkb.find_by_sql ["..some large sql query..."] for of in ofs # About 700-1000 elements ops = Operation.find(..the single query..) etc. end 

以下是这些方法的ruby-prof结果:

  %self total self wait child calls name 32.19 97.91 97.91 0.00 0.00 55 IO#gets (ruby_runtime:0} 28.31 86.39 86.08 0.00 0.32 32128 Mysql#query (ruby_runtime:0} 6.14 18.66 18.66 0.00 0.00 12432 IO#write (ruby_runtime:0} 0.80 2.53 2.42 0.00 0.11 32122 Mysql::Result#each_hash (ruby_runtime:0} 

问题是:我无法真正避免那些单一的查询。 我有数以千计的事件,我必须从中计算复杂的数据。 现在我在那些方法上使用memcached,除非你是第一个请求页面的人。

我会同意其他人的意见。 你必须描述。 在您知道具体导致缓慢的原因之前,对代码执行任何操作都没有意义。 试图在不了解原因的情况下解决问题,就像感觉不舒服,决定进行大量手术,直到感觉好转。 首先诊断您的问题。 它可能像网络设置一样小,也可能是代码中的一条坏线。

分析的一些提示:

如何描述您的Rails应用程序

性能测试Rails应用程序

在Forge – Profiling Rails应用程序中

一旦找到瓶颈,你就可以弄明白该怎么做了。

我推荐这些video: Railslab Scaling Rails

现在根据教授结果进行修订:

好。 现在您可以看到您的问题是您正在使用基于循环查看另一个活动记录查询结果的查询进行某种计算,我建议您研究构建一个自定义SQL语句,结合您的初始选择标准和获得你需要的循环计算。 您可以通过优化SQL来加快速度。

每个视图访问中正在执行多少个0-10ms查询? 您的数据模型的哪些部分被引用? 您是否正在使用:include以获得对您的关联的热切加载?

Rails和你做的一样慢。 了解速度(通常!)

扩展上面的内容,你是否有has_many关联,特别是你的视图引用了“很多”方而没有:include ? 这会导致主表上的find(:all)通过连接到详细信息来执行 – 如果您有大量的详细记录并且正在单独处理所有这些记录,这可能会变得昂贵。

像这样的东西:

 Master.find(:all, :include => :details) 

…可能有帮助。 但仍然从稀疏信息中猜测。

这里有一个关于这个主题的旧Railscast

虽然RnR 的声誉很慢 ,但这听起来太极端了,不能成为语言的一个简单问题。

您应该运行一个分析器来确定哪些function很慢以及为什么。 减慢Web应用程序最常见的是“ n + 1问题 ”。 也就是说,当您的数据库中有n个数据项时,该应用程序会对数据库进行单独的查询,而不是生成一个获取它们的查询。 但是在运行探查器之前你无法知道 。 ruby-prof是我用过的一个剖析器。

根据个人资料结果编辑编辑:

我坚信你总能删除一个查询循环。 正如Mike Woodhouse所说,Rails的方法是使用has_many或其他关联来指定表之间的关系,然后让rails自动生成表连接,这是明确的,快速的和“Rails方式”。 但是如果你刚开始使用裸SQL,或者在这种情况下关联不起作用,你可以自己生成适当的连接。 如果所有其他方法都失败了,您可以创建一个视图或非规范化表,其中包含先前通过循环找到的结果。 实际上,您必须遍历生成的查询这一事实可能表明您的表设计本身存在一些缺陷。

总而言之,如果缓存您的查询结果对您来说效果很好,那么请坚持下去。 在需要时进行优化。

这不正常。 你有一些让你失望的逻辑。 尝试评估您认为需要花费很长时间的代码的一些部分,看看是否有帮助。 如果确实如此,那么您需要弄清楚如何优化该逻辑。

你们在循环遍历大量对象的循环中做了很多计算,当然它会很慢。

这些类型的问题可以出现在任何语言或框架中。 虽然Ruby没有其他语言那么快,但它在大多数时候都足够快。 如果您需要不断地使用大型数据集进行计算,那么Ruby可能不适合您。 考虑编写一个Ruby C扩展,它将处理您的性能耗尽代码。 但首先只是尝试诊断和重构。

最后,查看RubyProf以查看它是否可以帮助您找到瓶颈。

前两个答案很有帮助,尤其是使用性能监控工具。 我使用New Relic RPM ,它在过去帮助了我很多。

但是,当你试图从3秒加速到1秒以下时,这些工具真的是最好的。

在任何正常情况下,渲染视图2-4分钟绝对不正常。

您能否向我们展示一些开发日志,以找出瓶颈所在?

您是否包括浏览器将图像,javascripts或其他文件加载到此总测量中所需的时间?

这么长的执行时间会让我怀疑网络问题 – 也许DNS查询在主DNS服务器上超时?

您可以尝试使用JRuby或切换到Ruby 1.9。
它们都应该会带来巨大的性能提升。
JRuby的问题是使用C的gem不会编译/工作。 有些Java等价物是由jruby的“gem”应用程序安装的,但有些gem根本不起作用

你基本上会遇到与Ruby 1.9相同的问题。 一点点的语法改变了,但主要的问题是,大量的gem不再起作用了。 人们正在进行更新(请查看http://isitruby19.com/上的进度)

为什么不预先获取所有数据并让你的for循环在内存中找到它,而不是每次都查询数据库? 对单个视图的1000次查询表明您的设计严重错误。

这个主题有一些很好的屏幕演员http://railslab.newrelic.com/scaling-rails

像fragmet缓存和使用:include(避免n + 1)之类的东西可以提供帮助。 听起来你已经在使用memcached,那么为什么不curlurl来预取缓存呢?

当我将服务器绑定到盒子ip地址而不是0.0.0.0时,这对我来说加速了。

在执行任何操作之前,您可能会首先分析代码,但是,for循环内部的查询是导致性能问题的常见原因,乍一看这似乎是您的问题。 你可能会在这里找到一个实用的分析器:

正如在其他答案中已经说过的那样,如果两个模型都相关,则应该急切加载关联,这意味着指示Active Record执行连接查询:

 #left outer join ofkbs=Ofkb.includes(:operation).where(name: "banana") 

如果您不需要ofkbs而只需要操作,则可以执行内部联接

 #inner join (discards the Ofkbs that do not have any operation) operations=Operation.joins(:ofkb).where(ofkb:{name:"banana"}) 

此解决方案仅预先形成一个查询,并允许您随后遍历已从数据库收集的数据:

 operations=ofkbs.map{|of| of.operations}.flatten operations.each do |o| do_whatever_you_want_with_operation(o) end 

如果查询非常复杂,则应使用arel 。