Rails 3 应用程序服务器启动时间很长。

18

更新2:这是Ruby1.9.2加载文件的已知错误/特性。http://twitter.com/#!/rails/status/72801149769621504

更新:一开始我认为这是一个问题,但在对此进行了一些研究后,我认为这可能无法解决。我想发布这篇文章,以防其他人也遇到相同的情况,并想知道在Rails和Bundler内部发生了什么。

有别的开发者在他们的Rails 3应用中看到长时间的加载时间吗?我在environment.rb、application.rb、boot.rb和railties/lib/rails/initializable.rb中放置了计时器。时间以秒为单位计算,经过的时间是自上次记录时间以来的时间。生产加载时间需要更长的时间。部分原因是硬件较少,另一部分原因是由于eager_load!(也许是Thin vs Mongrel的缘故) 。看起来Bundler占据了大量的加载时间,我想这是可以预料的。我测试了一个应用程序在dev和prod中,还有一个空白的应用程序在dev中。我测试了2个应用服务器,只是想看看是Thin导致的。在prod中,我也看到类似的情况(由于2.2.15中的生成行为,使其无法使用)。我针对边缘Rails进行了测试,dev中的性能略差14.5秒比14.2秒。如果我删除我的测试依赖项,则可以节省2-3秒,但运行测试时无济于事。我想只是稍微有点恼人,等待所有我的Thin实例重新启动需要5分钟,并且在我的测试运行之前要等待15秒,但从生产率方面来看,这是可以接受的折衷方案,因为我使用Rails 3获得了更高的生产率。如果有人有任何想法来帮助加快速度,我会倾听的。以下是测试结果:

注意:我的Rails 2.3应用程序在dev中加载时间不到3秒(尽管自从转移到rails3以来,我已经将一些代码转换为引擎并添加了haml和twitter_oauth宝石)

**以上所有测试均在Rails 3RC和Ruby 1.9.2rc2中进行。

在Rackspace云服务器2GB实例上使用Thin和CentOS 5.5 - 测试App #1,有24个gem依赖项

启动env.rb- 总计=0
  启动app.rb- 经过0.00110546秒。总计=0.001180052
    启动boot.rb- 经过0.000600488秒。总计=0.00178644     
    结束boot.rb- 经过0.7935529秒。总计=0.795507318  
    启动require rails/all- 经过0.000189127秒。总计=0.795701199  
    结束require rails/all- 经过1.086998364秒。总计=1.882735263  
    启动Bundler require- 经过0.000109708秒。总计=1.88285043  
    结束Bundler require- 经过8.955853243秒。总计=10.838746673  
  结束app.rb- 经过0.062975913秒。总计=10.901753753  
  # /railties-3.0.0.rc/lib/rails/initializable.rb 
  启动run initializers- 经过0.000145906秒。总计=10.901910186  
    加载environment_config- 经过0.116689774秒。总计=11.018632298  
    初始化cache- 经过0.246161343秒。总计=11.320543397  
    active_record.initialize_database- 经过0.080047485秒。总计=11.400961893  
    bootstrap_hook- 经过1.034189984秒。总计=12.451309104  
    active_support.initialize_time_zone- 经过1.969821814秒。总计=14.448777651  
    action_controller.set_configs- 经过0.594991537秒。总计=15.044692126  
    will_paginate.active_record- 经过0.324460921秒。总计=15.386837641  
    will_paginate.action_view- 经过1.904889132秒。总计=17.328981523  
    add_view_paths- 经过0.087811847秒。总计=17.42011881  
    load_init_rb- 经过0.151282681秒。总计=17.709093173  
    load_init_rb- 经过0.362241273秒。总计=18.071865548  
    load_config_initializers- 经过0.144051305秒。总计=18.217433492  
    build_middleware_stack- 经过2.569453884秒。总计=20.826842081  
    eager_load!- 经过4.165919064秒。总计=24.99280168  
    finisher_hook- 经过0.48795935秒。总计=25.480807439  
    repopulate_roles- 经过0.504085662秒。总计=25.984901297  
  结束run initializers- 经过约0.00005秒。总计=25.985617783  
结束env.rb- 经过约0.00006秒。总计=25.985683903  

在Max OSX 10.5.8,2.66 Core2duo,4GB RAM上使用Mongrel - 测试App #1,有24个gem依赖项

启动boot.rb (Bundler.setup) - 经过2.0e-05秒。总计=3.1e-05  
结束boot.rb (Bundler.setup) - 经过2.352435秒。总计=2.352915  
启动app.rb - 经过0.084945秒。总计=2.437866  
  启动require rails/all- 经过0.000181秒。总计=2.438049  
  结束require rails/all- 经过0.489425秒。总计=2.927485  
  启动Bundler.require(:default, Rails.env)- 经过5.6e-05秒。总计=2.927544  
  结束Bundler.require(:default, Rails.env)- 经过5.16162秒。总计=8.089

非常感谢您分享实验结果。我不确定您使用的是哪个版本的Ruby,但我猜测Ruby >=1.9会加快速度。 - Dmytrii Nagirniak
1
我正在使用 Ruby 1.9.2。性能是加载 gem 的结果,也与 Rails 框架的模块化有关。你的应用程序依赖项越多,启动所需时间就越长,这是有道理的。我怀疑,在短期内核心团队无法加快速度...至少目前看来是如此。 - johnmcaliley
我在想为什么没有那么模块化的 Rails 2 启动得这么快... 那么也许问题应该是:为什么 bundler 要花那么长时间来加载所有依赖关系? 它会解决这些依赖关系吗,还是只是盲目地加载它们? 我猜,如果我们可以禁用 bundle 的所有智能功能,并“只加载”依赖项,那么它会加快速度... - Dmytrii Nagirniak
我相信解决问题不是问题。Rails 2的代码库可能比3要小得多。他们添加了额外的抽象层,例如Active Model,以使框架更加模块化。更多的代码=更长的启动时间。当你运行'bundle install'时,它会解析并在本地安装gems,而bundler只是在启动时将这些加载到你的环境中。我还没有太多时间来进一步研究这个问题,但我会尽快发表另一个评论,一旦我有机会进行更多的调试。 - johnmcaliley
你是怎么钩取一些代码来测量加载时间的呢?你只是重写了require()函数并调用了super()吗? - Wilhelm
不是那么高科技;-) 我记不清了,但我想我只是添加了一个变量 'start = Time.now',然后在这些文件的每个点上添加一个打印语句并执行 'Time.now - start'。 - johnmcaliley
3个回答

2

由于这是一个相当古老的问题:您是否已经使用Rails 3的发布版本进行了测试?

那是很长时间,但最终毫无意义。我的Rails应用程序可以连续运行数月,因此这只占总运行时间的百分之一的一小部分。

您是否有大量依赖项需要Bundler处理?我可以在任何环境中在不到2秒的时间内启动我的Rails 3应用程序,但我只使用了非常少的第三方gems。


我现在正在使用Rails 3的官方版本。虽然我还没有重新运行基准测试,但启动时间并没有明显改善。是的,我的应用程序有很多依赖项,你可以看到一个空的Rails 3应用程序在我的服务器上的基准测试中启动大约需要3秒钟。当我尝试使用Passenger并等待进程生成时,这是一个烦恼。我每周至少部署几次更改,在我的系统上有数百个用户,30秒的等待或停机是一个问题。我切换到Thin并使用滚动重启,所以之后这真的不是一个问题了。 - johnmcaliley
此外,在Passenger 3 beta上,这个问题已经不再是一个问题了,因为它具有零停机重启和新的生成架构。所以你是对的...除了可能进行测试(如果你没有使用类似spork的东西),这基本上是毫无意义的。 - johnmcaliley
这个问题仍然存在...但是在开发过程中需要很长时间,这让人感到沮丧。 - rtdp

2
Bundler常常会花费超过一半的时间来加载gem包。在开发/测试模式下,你是否有加载的依赖项是不必要的?例如,我的一些gems仅在resque工作器或其他脚本中使用。为了在开发/测试模式下获得适度的启动速度提升,你可以添加:require => false,然后在需要时手动加载它们。
在这样做之前,我通常会对require语句(在lib/bundler/runtime.rb中)进行分析,以确定它们是否值得剔除。

我在开发/测试中实际上有更多的宝石.. mongrel、cuke、rspec等等。;-) 我同意这是一个很好的练习。如果你仔细查看并确保你实际上正在使用gemfile中的所有内容,那么它肯定可以为你节省几秒钟的时间。 - johnmcaliley

0
我有三个Rails 3应用程序,并且正在从2.3.8迁移其中一个。运行在Rails 2.3.8上的那个应用程序加载需要4秒钟时间,而在一半处于Rails 3的分支需要12秒钟时间。所有其他的Rails 3项目需要20到30秒钟才能加载完毕。当我看到别人的Rails应用程序加载只需要3秒钟时,这真的让我感到非常沮丧。自从我迁移到Rails 3以来,我就一直在苦苦寻找原因,以为是我的环境出了问题。

如果您没有依赖项并且正在运行顶级硬件,则可能只需要3秒钟。但我仍然没有看到包含依赖项的任何应用程序少于10秒钟的情况。 - johnmcaliley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接