2017-04-21 76 views
1

我們在Heroku上部署了一個Rails應用程序(RAM-512mb)。我們有一個返回13k +對象的API(Growing)。 Heroku應用的內存跨越了200%的內存。如果我重新啓動我的應用程序,並打這個特定的API 3-4次,內存立即跨越內存大小。它是內存泄漏嗎?內存收費太多了嗎?內存超過生產中的Rails應用程序(部署在Heroku上)

Controller code: 
def respond 
    @us_anss= UsAns.respond_to_query(params) 
end 

型號代碼

def respond_to_query 
anss = self.all.includes(:a, :b, :c) 
anss.each do |ans| 
    ans.class.class_eval {attr_accessor :coun, :date, :rec_id} 
    ans.coun = ans.user.coun 
    ans.date = ans.created_at.to_date 
    if ans.rel_id.nil? 
     ans.rec_id = nil 
    else 
     ans.rec_id = ans.user.opponent(ans.rel).id 
    end 
    end 
    return anss 
end 

Rabl的代碼

Rail code 
attributes :ans => :message_content, :user_id => :sen_id 
attributes :rec_id, :coun, :date, :latitude, :longitude 
collection @us_anss, :object_root => false 
child :que do |us_wer| 
    attributes :que => :text 
    attributes :id, :tri_date 
end 

的Gemfile

source 'https://rubygems.org' 
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails' 
gem 'rails', '~> 5.0.0', '>= 5.0.0.1' 
gem 'puma', '~> 3.0' 
gem 'rabl' 
# Also add either `oj` or `yajl-ruby` as the JSON parser 
gem 'oj' 
# gem for dashboard 
gem 'rails_admin', '~> 1.0' 
# Gem for push notifications 
gem 'rpush', :git => "git://github.com/moldedbits/rpush.git", :branch => 'master' 
# Rack::Cors provides support for Cross-Origin Resource Sharing (CORS) 
for Rack compatible web applications. 
gem 'rack-cors', :require => 'rack/cors' 

# Gem for scheduling tasks 
gem 'rufus-scheduler' 

gem 'jquery-rails', '~> 4.2', '>= 4.2.1' 
gem 'bootstrap-sass', '~> 3.3', '>= 3.3.7' 
gem 'sass-rails', '~> 5.0', '>= 5.0.6' 
gem 'haml', '~> 4.0', '>= 4.0.7' 
gem 'newrelic_rpm' 
# Use ActiveModel has_secure_password 
gem 'bcrypt', '~> 3.1.7' 
gem 'geocoder' 
# Use Capistrano for deployment 
# gem 'capistrano-rails', group: :development 

# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible 
# gem 'rack-cors' 

gem 'obscenity', '~> 1.0', '>= 1.0.2' 
group :development, :test do 
    gem 'dotenv-rails' 
    gem 'factory_girl_rails' 
    gem 'shoulda-matchers', '~> 3.1', '>= 3.1.1' 
    # Call 'byebug' anywhere in the code to stop execution and get a debugger console 
    gem 'byebug', platform: :mri 
    gem 'rspec-rails', '~> 3.5' 
    gem 'airborne' 
    gem 'faker', '~> 1.6', '>= 1.6.6' 
    # Use sqlite3 as the database for Active Record 
end 
gem 'rake', '>=11.3.0' 
gem 'scout_apm' 
group :development do 
    gem 'sqlite3' 
    gem 'listen', '~> 3.0.5' 
    gem 'letter_opener' 
    # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring 
    gem 'spring' 
    gem 'spring-watcher-listen', '~> 2.0.0' 
end 
gem 'exception_notification' 
group :production do 
    gem 'pg' 
end 
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem 
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] 

我甩生產數據庫,並與derailed_benchmarks寶石跑了本地。我使用這個特性來獲得運行時的內存大小。

PATH_TO_HIT=/users/new bundle exec derailed exec perf:mem_over_time 

這裏是上面的命令的日誌

86.640625 
41.62109375 
36.15625 
86.3671875 
73.2265625 
72.78515625 
93.78515625 
163.53515625 
192.04296875 
168.1953125 
221.4609375 
281.02734375 
92.8046875 
315.203125 
150.9609375 
209.9453125 
324.18359375 
327.5390625 
346.625 
346.76953125 
353.06640625 
355.0 
360.96484375 
369.99609375 
385.41015625 
388.75 
391.203125 
378.58203125 
375.23046875 
387.6640625 
389.33984375 
390.8828125 
399.21484375 
415.59375 
415.8359375 
419.88671875 
435.46484375 
437.91796875 
430.77734375 
417.00390625 
425.43359375 
425.58984375 
430.51171875 
425.8671875 
430.2578125 
431.16796875 
390.44140625 
358.81640625 
393.890625 
399.44140625 
403.44921875 
412.859375 
363.3515625 
359.390625 
379.11328125 
398.55859375 
400.31640625 
406.91015625 
423.31640625 
420.875 
425.875 
426.91796875 
426.5859375 
430.390625 
386.78515625 
377.77734375 
374.86328125 
252.625 

我用頂部看存儲器大小和命中API本地50倍。這裏是頂部的日誌 Tops stats

我在開發和生產中使用新的遺蹟。它表明響應時間的主要部分是由控制器方法消耗的。

+1

爲什麼你需要返回所有13K +元素一個要求嗎?這不會縮放。爲什麼你需要重新計算'coun','date'和'rel_id'對每個請求的每個元素?難道不能將這些值存儲在數據庫中,或者至少在數據庫中計算它們嗎? – spickermann

回答

0

您可以在本地停用GC以找出需要佔用大量內存並嘗試對其進行優化的內容。

但這裏是一些嘗試:

  • 你是正確的,包括關係?很顯然,你只需要包括user: :opponent
  • class.class_eval在你的each區塊似乎是一件非常糟糕的事情。
1

而不是一次返回所有13k +項目,你可以批量返回它。這樣你就不會消耗盡可能多的RAM。我建議你在使用功能「find_each」的1000批次返回記錄。您可以檢查this鏈接。

1
Model.all 

會同時保存所有ActiveRecord對象。這是一個非常糟糕的主意。尤其是如果您正在使用includes急切加載其他三個關聯模型。

我建議您使用#find_each方法來代替集合,允許垃圾收集器在處理每個批處理時回收其消耗的內存。

不建議使用這麼多數據返回單個響應。 的尋呼系統應該在你的API,它使用戶有機會逐步消耗的數據來實現。

相關問題