Как заставить Ruby собирать мусор и запускать Heroku - PullRequest
0 голосов
/ 24 октября 2019

У меня есть веб-сервис в приложении Ruby on Rails, размещенном на Heroku.

Когда эта служба работает, используется много памяти. Я вызываю службу порциями, поэтому после каждой порции вся эта память больше не нужна. Тем не менее, он превышает квоту heroku и начинает выдавать ошибки R14.

Отслеживая память, память никогда не выключается и GC.stat[:minor_gc_count] не изменяется, указывая на то, что сборка мусора не запущена, хотяхост находится выше квоты памяти.

Как настроить сборку мусора ruby, чтобы указать, что в квоте должна выполняться сборка мусора?

Я установил конфигурацию RUBY_GC_MALLOC_LIMIT_MAX ниже иниже, но ничего не помогает.

heroku config:add RUBY_GC_MALLOC_LIMIT_MAX=320.megabyte

Код:

class Admin::Api::V1::CvesController < ApiController
  def upload
    result = Cve.transaction_upload_content(params['upload_stream'].tempfile)
    render json: result, status: result[:errors] ? :unprocessable_entity : :created
  end
end

  def self.transaction_upload_content(upload_file)
    byte_content = upload_file.read

    result = {}
    status = :unprocessable_entity
    transaction do
      result = load_cve_content(JSON.parse(byte_content))

      raise ActiveRecord::Rollback if result[:errors]
      status = :created
    end
    result.merge( status: status )
  end


  def self.load_cve_content(cves_ary)
    cve_keys = []
    errors = []
    begin
      cves_ary.each do |cve_attrs|
        attributes = cve_attrs.slice(*columns.map{|col| col.name})
        cve = find_or_initialize_by(cve_key: attributes['cve_key'])
        cve.assign_attributes(attributes)
        if cve.save
          cve_keys << cve.cve_key
        else
          errors += "Error updating #{attributes['cve_key']}: #{cve.errors.full_messages.to_sentence}"
        end
      end
    rescue Exception => except
      errors << except.message
    end
    ActiveSupport::HashWithIndifferentAccess.new(cve_keys: cve_keys, errors: errors.empty? ? nil : errors)
  end

Я загружаю 12 000 записей, по 10 на один вызов API:

enter image description here

Я сделал обновление кода в 2 часа дня по Гринвичу, которое перезапустило динамометры, а затем трижды пробежало весь набор из 12 000 записей. Из-за 10-минутного разрешения я подождал 10-20 минут, перезапустил динамометры незадолго до 15:00, подождал 20 минут, а затем пробежал весь набор из 12 000 записей двадцать раз.

Вот мои соответствующие настройки конфигурации Heroku:

RUBY_GC_HEAP_FREE_SLOTS:       600000
RUBY_GC_HEAP_GROWTH_FACTOR:    1.25
RUBY_GC_HEAP_GROWTH_MAX_SLOTS: 300000
RUBY_GC_HEAP_INIT_SLOTS:       600000
RUBY_GC_MALLOC_LIMIT:          256.megabyte
RUBY_GC_MALLOC_LIMIT_MAX:      320.megabyte
RUBY_GC_OLDMALLOC_LIMIT:       256.megabyte
RUBY_GC_OLDMALLOC_LIMIT_MAX:   512.megabyte
...