Rails应用程序配置访问速度慢 - 为什么?

时间:2013-05-05 08:53:03

标签: ruby-on-rails app-config

我们总是习惯将应用程序配置放入环境文件中。这对生产管理没有好处,所以现在我们通过初始化程序加载它:

# myinitializer.rb
ApplicationConfig = YAML.load_file("#{Rails.root}/config/application/default.yml").symbolize_keys()

一旦我们开始通过ApplicationConfig访问配置,应用程序测试性能就会变得更糟。一个rspec套件从4秒下降到30。

在我们的应用程序控制器中,我们需要使用before_filter执行某些操作,其工作方式如下:

before_filter :extra_control

def extra_control
  if ApplicationConfig.some_flag
    ...
  end
end

声明指向ApplicationConfig的变量可以完全恢复性能:

config = ApplicationConfig

def extra_control
  if config.some_flag
    ...
  end
end

为什么呢?为什么通过全局变量访问它会破坏性能?我们在视图和其他控制器的整个代码库中执行此操作。我们需要以不同的方式做到这一点,例如通过将实例变量注入所有控制器?

编辑我们确实验证了从YAML加载配置的代码在任何一种情况下都会被调用一次,因此重复加载似乎不是根本原因。

编辑:事实证明这是一个由设置变量引起的错误,该变量被加载为字符串而不是布尔值,导致应用程序进入测试睡眠模式:(抱歉,谢谢你的尝试。我生命中的3天我永远不会回来!

4 个答案:

答案 0 :(得分:0)

我无法说明为什么你的方法很慢,但是处理设置的不同方式可能值得研究。我更喜欢使用包含配置信息的单例类:

class SiteSettings
    def initialize
        @settings = {}
    end

    @@instance = SiteSettings.new

    def set_setting(key, value)
        @settings ||= {}
        @settings[key] = value
    end

    def self.setting(key, value)
        @@instance.set_setting(key, value)
    end

    def settings
        @settings
    end

    def self.method_missing(meth, *args, &block)
        if @@instance.settings.has_key?(meth)
            @@instance.settings[meth]
        else
            super
        end
    end

    setting :test_setting, 'test'
    setting :another_test_setting '.....'
end

puts SiteSettings.test_setting
puts SiteSettings.another_test_setting

Discourse app采用了类似的方法。

答案 1 :(得分:0)

尝试使用const:

APPLICATIONCONFIG = YAML.load(File.read(File.expand_path("#{RAILS_ROOT}/config/application/default.yml", __FILE__)))

APPLICATIONCONFIG = YAML::load(File.open("#{RAILS_ROOT}/config/application/default.yml"))

我认为它会使你的文件变慢因为加载文件而不是打开/读取。

答案 2 :(得分:0)

我认为这将有助于弄清楚YAML文件load \ read是否很慢,或者YAML解析是否很慢。我的猜测是,每次调用ApplicationConfig变量时,ruby都会解析YAML文件。您可以尝试将其重命名为APPLICATION_CONFIG,如下所示:

APPLICATION_CONFIG = YAML.load(File.read(Rails.root.join('config', 'application', 'my_config.yml')))

请不要在所有控制器中注入实例变量:)

答案 3 :(得分:0)

这里的其他答案没有什么区别 - 这是由一个无关的问题引起的。记录

  • 初始化程序仅由rspec
  • 调用一次
  • 使用ApplicationConfig还是APPLICATION_CONFIG
  • 没有区别
  • 分配给变量也没有产生速度差异