Подтвердить что ты не робот

Rails 3 + Heroku: узнайте, как использовать динамическую память

Есть ли способ узнать, сколько памяти использует веб-диктофон heroku? Скажем, я хочу написать задачу рейка, которая периодически запускается и проверяет использование каждой динозависимой памяти. Как я могу это сделать? Спасибо!

4b9b3361

Ответ 1

Я принял предложение из принятого ответа и реализовал парсер файловой системы /proc с агрегированием и пороговым отличием. Я нашел это весьма полезным при отладке некоторых проблем памяти Ruby 2.0 на Heroku. Получите код, также включенный здесь для удобства.

# Memory snapshot analyzer which parses the /proc file system on *nix
#
# Example (run in Heroku console):
#
#    ms = MemorySnapshot.new
#    1.upto(10000).map { |i| Array.new(i) }; nil
#    ms.snapshot!; nil
#    ms.diff 10
#    => {"lib/ld-2.11.1.so"=>156, "heap"=>2068, "all"=>2224}
#
class MemorySnapshot

  attr_reader :previous
  attr_reader :current

  def initialize
    snapshot!
    @previous = @current
  end

  # Generates a Hash of memory elements mapped to sizes of the elements in Kb
  def snapshot!
    @previous = @current
    @current = reduce(names_with_sizes)
  end

  # Calculates the difference between the previous and the current snapshot
  # Threshold is a minimum delta in kilobytes required to include an entry
  def diff(threshold = 0)
    self.class.diff_between previous, current, threshold
  end

  # Calculates the difference between two memory snapshots
  # Threshold is a minimum delta in kilobytes required to include an entry
  def self.diff_between(before, after, threshold)
    names = (before.keys + after.keys).uniq
    names.reduce({}) do |memo, name|
      delta = after.fetch(name) { 0 } - before.fetch(name) { 0 }
      memo[name] = delta if delta.abs >= threshold
      memo
    end
  end

  private

  def reduce(matches)
    total = 0
    current_name = nil
    matches.reduce(Hash.new { 0 }) do |memo, match|
      current_name = match[:name] || current_name
      size = match[:size].to_i
      total += size
      memo[current_name] += size
      memo
    end.tap { |snapshot| snapshot['all'] = total }
  end

  def names_with_sizes
    smap_entries.map do |line|
      /((^(\/|\[)(?<name>[^ \]]+)\]?\s+)|(^))(?<size>\d+)\s/.match(line)
    end
  end

  def smap_entries
    smaps.
        gsub(/^(([^Sa-f0-9])|(S[^i]))[^\n]+\n/m, '').
        gsub(/\nSize:/m, '').
        gsub(/[0-9a-f]+-[0-9a-f]+.{6}[0-9a-f]+ [0-9a-f]+:[0-9a-f]+ [0-9a-f]+\s+/i, '').
        split("\n")
  end

  def smaps
    File.read("/proc/#{Process.pid}/smaps")
  end
end

Ответ 2

Там также есть родной способ Heroku сделать это сейчас. Heroku выкалывала функцию показателей выполнения журналов, которая будет вводить информацию загрузки процессора и использования памяти в поток ведения журнала. Эти журналы имеют идентификатор источника (например, "web.1" ) и уникальный уникальный идентификатор, так что вы можете разделить динамики. Это выглядит примерно так:

source=web.1 dyno=heroku.2808254.d97d0ea7-cf3d-411b-b453-d2943a50b456 sample#load_avg_1m=2.46 sample#load_avg_5m=1.06 sample#load_avg_15m=0.99
source=web.1 dyno=heroku.2808254.d97d0ea7-cf3d-411b-b453-d2943a50b456 sample#memory_total=21.00MB sample#memory_rss=21.22MB sample#memory_cache=0.00MB sample#memory_swap=0.00MB sample#memory_pgpgin=348836pages sample#memory_pgpgout=343403pages

Чтобы включить это, просто запустите:

heroku labs:enable log-runtime-metrics
heroku restart

Ответ 3

Поскольку Heroku работает на экземпляре Amazon с Linux, вы можете использовать файловую систему proc для получения системных данных времени исполнения. Файл /proc/<pid>/smaps содержит информацию о памяти в текущем процессе и все библиотеки, которые он загружает. Для размера резидентного процесса сделайте следующее:

f = File.open("/proc/#{Process.pid}/smaps")
f.gets # Throw away first line
l = f.gets # Contains a string like "Size:               2148 kB\n"
l =~ /(\d+) kB/  # match the size in kB 
f.close
$1.to_i  # returns matched size as integer

Обновление: файловая система proc имеет еще лучший источник, /proc/<pid>/status. Там содержится запись VmRSS: для общей части резидентной памяти и VmHWM: для самой используемой резидентной памяти (знак высокой воды). Более подробную информацию об этих и других областях см. В разделе Документы ядра Linux для файловой системы proc.