【问题标题】:Why are my tests slow after upgrading rails from 3.1.0 to 3.2.0?为什么将 rails 从 3.1.0 升级到 3.2.0 后我的测试变慢了?
【发布时间】:2012-08-04 01:22:36
【问题描述】:

我遵循了这些升级说明:http://railscasts.com/episodes/318-upgrading-to-rails-3-2

这是我的三个小的升级更改:

(1) Gemfile

-gem 'rails', '3.1.0'
+gem 'rails', '3.2.0'

-gem 'rack', '1.3.3'
+#gem 'rack', '1.3.3'

 group :assets do
-  gem 'sass-rails', '  ~> 3.1.0'
-  gem 'coffee-rails', '~> 3.1.0'
-  gem 'uglifier'
+  gem 'sass-rails', '  ~> 3.2.3'
+  gem 'coffee-rails', '~> 3.2.1'
+  gem 'uglifier', '     >=1.0.3'
   gem 'asset_sync'
 end

(2) config/environments/development.rb

+  config.active_record.mass_assignment_sanitizer = :strict
+  config.active_record.auto_explain_threshold_in_seconds = 0.5

(3) config/environments/test.rb

-  config.assets.allow_debugging = true
+  config.active_record.mass_assignment_sanitizer = :strict

在升级之前,我的测试如下所示(每个测试不到一秒):

...
StockroomTest:
     PASS stockroom must have a name (0.03s) 
     PASS stockroom name must be unique (0.01s) 
     PASS stockroom with name is valid (0.00s) 
...
Finished in 1.604118 seconds.
29 tests, 90 assertions, 0 failures, 0 errors, 0 skips
...
StockroomsControllerTest:
     PASS should create stockroom (0.04s)
     PASS should destroy stockroom (0.02s)
     PASS should get edit (0.14s)
     PASS should get index (0.11s)
     PASS should get new (0.03s)
     PASS should not destroy stockroom (0.04s)
     PASS should show stockroom (0.13s)
     PASS should update stockroom (0.02s)
...
Finished in 12.572911 seconds.
115 tests, 166 assertions, 0 failures, 0 errors, 0 skips
...
MiscellaneousTest:
     PASS get campaigns#index should redirect to newsletters#index (1.83s)
     PASS get /campaigns should redirect to / when logged out (0.06s)
Finished in 1.793070 seconds.
2 tests, 3 assertions, 0 failures, 0 errors, 0 skips

之后(每次测试需要 1 秒):

StockroomTest:
     PASS stockroom must have a name (1.29s)
     PASS stockroom name must be unique (1.30s)
     PASS stockroom with name is valid (1.27s)
...
Finished in 41.135808 seconds.
29 tests, 90 assertions, 0 failures, 0 errors, 0 skips
...
StockroomsControllerTest:
     PASS should create stockroom (1.30s)
     PASS should destroy stockroom (1.29s)
     PASS should get edit (1.33s)
     PASS should get index (1.43s)
     PASS should get new (1.41s)
     PASS should not destroy stockroom (1.31s)
     PASS should show stockroom (1.36s)
     PASS should update stockroom (1.31s)
...
Finished in 161.803235 seconds.
115 tests, 166 assertions, 0 failures, 0 errors, 0 skips
...
MiscellaneousTest:
     PASS get /campaigns should redirect to /newsletters when logged in (5.27s)
     PASS get /campaigns should redirect to / when logged out (1.67s)
Finished in 7.034593 seconds.
2 tests, 3 assertions, 0 failures, 0 errors, 0 skips

以下是上述单元测试之一的示例。现在(升级后)运行大约需要 1.3 秒,而之前不到 0.01 秒。

test/unit/stockroom_test.rb

require 'test_helper'

class StockroomTest < ActiveSupport::TestCase
  fixtures :stockrooms

  test "stockroom with name is valid" do
    assert stockrooms(:wine_cellar).valid?, 'tried new wine_cellar'
  end

我知道固定装置不受欢迎,我确实打算认真研究工厂,但目前这是我的困境。这是相关的夹具:

test/fixtures/stockrooms.yml

wine_cellar:
  id: 1
  name: wine cellar

Stockroom 上仅有的两个验证是 presenceuniqueness

注意:我正在同一台机器上运行另一个 rails 应用程序,尽管它正在运行 rails 3.2.5,并且几乎相同的单元测试(相同的两个验证的相同断言)在 0.465489 秒内完成(不到半第二)。

对于上述“具有名称的库房有效”测试,测试日志的相关部分如下所示:

 (0.9ms)  SET FOREIGN_KEY_CHECKS = 1
 (0.2ms)  BEGIN
 (84.8ms)  BEGIN
 (82.3ms)  BEGIN
 (83.4ms)  BEGIN
 (79.2ms)  BEGIN
 (82.1ms)  BEGIN
Stockroom Load (0.4ms)  SELECT `stockrooms`.* FROM `stockrooms` WHERE `stockrooms`.`id` = 1 LIMIT 1
Stockroom Exists (0.6ms)  SELECT 1 AS one FROM `stockrooms` WHERE (`stockrooms`.`name` = BINARY 'wine cellar' AND `stockrooms`.`id` != 1) LIMIT 1
 (0.1ms)  ROLLBACK
 (90.9ms)  ROLLBACK
 (85.7ms)  ROLLBACK
 (90.7ms)  ROLLBACK
 (81.4ms)  ROLLBACK
 (85.4ms)  ROLLBACK

为了比较,这是我的 rails 3.2.5 应用程序中的“等效”测试:

 (0.2ms)  SET FOREIGN_KEY_CHECKS = 1
 (0.1ms)  BEGIN
Email Load (0.4ms)  SELECT `emails`.* FROM `emails` WHERE `emails`.`id` = 980190962 LIMIT 1
Email Exists (2.8ms)  SELECT 1 FROM `emails` WHERE (`emails`.`email` = BINARY 'MyString' AND `emails`.`id` != 980190962) LIMIT 1
 (0.2ms)  ROLLBACK

【问题讨论】:

  • 我会亲自尝试使用最新的稳定 Rails 3.2.7,然后再进行其他操作
  • 谢谢,但不幸的是3.2.7 没有任何区别。
  • 您可以添加一个较慢的测试吗?
  • @John 我添加了一个速度较慢的测试(它们都比较慢,但我添加了一个最简单的测试)。
  • @user664833 你用的是什么Ruby版本?

标签: ruby-on-rails performance ruby-on-rails-3.1 upgrade ruby-on-rails-3.2


【解决方案1】:

我能想到的唯一答案是您的测试在交易处理方式上有所不同

如果一切正常,rails 应该将每个测试包装在事务中并回滚事务。所以你基本上只“模拟”写动作,不必每次测试后回滚数据库,从而节省大量时间。

如果是这样,您可能会在这里找到答案: ActiveRecord Rollback does not work in Rails test

只有您可以尝试明确打开该功能。

编辑:当您的输出显示您正在使用事务时,rails 环境的加载方式可能有所不同。请检查 spec_helper.rb 以了解奇怪的差异。

您可以查看这篇文章并检查在您的测试套件启动时是否发生了一些奇怪的事情: Rails 3 - Speed up Console Loading Time

【讨论】:

  • 嗯.. 但是3.1.03.2.0 之间有什么变化导致了这种情况吗?请注意,在另一个应用程序中(直接使用 rails 3.2.5 创建——即未从较低版本升级),在同一台机器上,几乎相同的测试不受此问题的影响(整个测试套件中也没有任何东西)。想法?
  • 不确定。但是,如果没有事务性固定装置正在进行,我预计测试数据库中的某些值会在某个时候发生变化。你有这种经历吗?
  • 我认为你在做某事!我更新了我的问题,日志显示了事务方面的显着差异(在另一个未受影响的应用程序的等效测试中,有多个嵌套的 BEGIN/ROLLBACK 事务与单个 BEGIN/ROLLBACK)。
  • self.use_transactional_fixtures = true 的测试没有任何区别,而self.use_transactional_fixtures = false 则有 no BEGIN/ROLLBACK 块(但也没有速度差异)。
  • 这听起来很奇怪。你也改变了数据库?听起来数据库几乎没有进行交易。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-02
相关资源
最近更新 更多