2013-05-05 41 views
7

Chúng tôi luôn sử dụng để đặt cấu hình ứng dụng của chúng tôi vào các tệp môi trường. Đó là không tốt cho quản lý sản xuất, vì vậy bây giờ chúng ta tải nó thông qua một initializer:Truy cập cấu hình ứng dụng Rails chậm - tại sao?

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

Ngay sau khi chúng tôi bắt đầu truy cập vào cấu hình thông qua ApplicationConfig, hiệu suất thử nghiệm ứng dụng trở nên tồi tệ hơn nhiều. Một bộ rspec giảm từ 4 giây để 30.

Trong điều khiển ứng dụng của chúng tôi, chúng tôi cần phải thực hiện một số hành động sử dụng một before_filter, mà làm việc như sau:

before_filter :extra_control 

def extra_control 
    if ApplicationConfig.some_flag 
    ... 
    end 
end 

Khai báo một trỏ biến để ApplicationConfig khôi phục hoàn toàn hoạt động :

config = ApplicationConfig 

def extra_control 
    if config.some_flag 
    ... 
    end 
end 

Tại sao? Tại sao truy cập thông qua biến toàn cầu phá hủy hiệu suất? Chúng tôi làm điều này trong toàn bộ cơ sở mã trong các khung nhìn và các bộ điều khiển khác. Chúng ta có cần thực hiện điều này một cách khác không, ví dụ: bằng cách tiêm một biến mẫu vào tất cả các bộ điều khiển?

Chỉnh sửa: chúng tôi đã xác minh rằng mã tải cấu hình từ YAML được gọi chính xác một lần, vì vậy việc tải lặp lại dường như không phải là nguyên nhân gốc.

Chỉnh sửa: nó chỉ ra rằng đây là lỗi do biến cài đặt được tải dưới dạng chuỗi thay vì boolean, khiến ứng dụng đi vào mẫu ngủ thử nghiệm :(Rất tiếc, cảm ơn bạn đã thử 3 ngày trong cuộc đời của tôi Tôi sẽ không bao giờ quay lại!

+0

Nó chỉ tồi tệ hơn trong môi trường thử nghiệm? Bạn đã kiểm tra ở giai đoạn nào trong môi trường thử nghiệm của bạn, trình khởi tạo được gọi? Bạn có thể làm như vậy thông qua trình gỡ rối hoặc bằng cách thêm một số bản in. – Anton

+0

Tôi không có dữ liệu về việc nó chỉ chậm trong thử nghiệm, nhưng tôi biết rằng initializer được gọi chính xác một lần cả trong thử nghiệm và phát triển - vì vậy nó không phải là một cuộc gọi khởi tạo lặp lại làm chậm nó xuống. – xcut

+0

Cũng lưu ý: hiệu suất làm chậm chỉ khi truy cập trực tiếp ApplicationConfig, nó biến mất khi gán nó cho một biến, như được hiển thị ở trên. – xcut

Trả lời

0

Những câu trả lời khác ở đây không tạo sự khác biệt - điều này đã được gây ra bởi một không liên quan vấn đề. Đối với hồ sơ

  • Initializers được gọi là đúng một lần bởi rspec
  • Nó không tạo sự khác biệt cho dù ApplicationConfig hoặc APPLICATION_CONFIG được sử dụng
  • Gán cho một biến không tạo sự khác biệt tốc độ hoặc
0

Tôi không thể nói lý do tại sao phương pháp của bạn chậm, nhưng có thể một cách khác để xử lý các cài đặt sẽ đáng để xem xét. lớp singleton chứa thông tin cấu hình:

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 t akes một cách tiếp cận tương tự.

+1

Cảm ơn bạn đã nỗ lực - vấn đề không liên quan đến cuối cùng. FYI, chúng tôi tải một tập tin YAML và sau đó vội vàng Hashie vào nó để tạo ra một đối tượng, điều này hoạt động rất tốt, không có hit hiệu suất. – xcut

0

Hãy thử const sử dụng:

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

hoặc

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

Tôi nghĩ rằng nó làm cho tập tin của bạn chậm vì tải tập tin nhưng không mở/đọc.

+0

Điều này không tạo ra bất kỳ sự khác biệt về tốc độ nào, tôi sợ. – xcut

0

Tôi nghĩ rằng nó sẽ giúp tìm hiểu xem tải tệp YAML đọc chậm hay phân tích cú pháp YAML chậm. Tôi đoán là ruby ​​đang phân tích cú pháp tệp YAML mỗi khi bạn gọi biến số ApplicationConfig của mình.bạn có thể thử đổi tên nó để APPLICATION_CONFIG như vậy:

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

Xin đừng tiêm một biến Ví dụ trong tất cả các bộ điều khiển của bạn :)

+0

Điều này không tạo ra sự khác biệt về tốc độ, tôi sợ. – xcut

Các vấn đề liên quan