2012-10-15 11 views
12

Gibt es eine Möglichkeit herauszufinden, wie viel Speicher ein Heroku-Web-Dyno verwendet? Nehmen wir an, ich möchte eine Rake-Aufgabe schreiben, die regelmäßig ausgeführt wird und die Speicherbelegung jedes Dynos überprüft. Wie könnte ich das tun? Vielen Dank!Rails 3 + Heroku: Die Speicherbelegung des Dyno-Speichers ermitteln

+1

Gibt es einen Grund, nicht New Relic zu benutzen? Monitoring> Dynos –

+1

Es zeigt die minimale, maximale und durchschnittliche Speicherauslastung aller Dynos kombiniert, und es gibt keine Möglichkeit, den Speicher eines bestimmten Dyno zu erhalten – sauronnikko

Antwort

3

Da Heroku auf einer Amazon-Instanz mit Linux ausgeführt wird, können Sie das Dateisystem proc verwenden, um Laufzeitsystemdaten abzurufen. Die Datei /proc/<pid>/smaps enthält Speicherinformationen für den laufenden Prozess und alle geladenen Bibliotheken. Für die residente Prozeßgröße, dies zu tun:

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 

Updates: Das proc-Dateisystem hat eine noch bessere Quelle, /proc/<pid>/status. Es gibt einen Eintrag VmRSS: für den gesamten residenten Speicherbereich und VmHWM: für den höchsten residenten Speicher (High Watermark). Weitere Einzelheiten zu diesen und anderen Feldern finden Sie unter The Linux Kernel docs for the proc file system.

+0

Auf Herokus Cedar-Stack gibt das die Größe der ersten Bibliothek zurück , nicht der Prozess selbst. Sie müssen wahrscheinlich alle Größen zusammen iterieren und addieren. – Sim

+0

Danke für die Aufklärung für Cedar. –

6

Ich nahm den Vorschlag aus der angenommenen Antwort und implementiert einen/proc-Dateisystem-Parser mit Aggregation & Schwellenwert-basierte Diffing. Ich fand es sehr nützlich beim Debuggen einiger Ruby 2.0 Speicherprobleme auf Heroku. Holen Sie sich die code, auch hier für die Bequemlichkeit enthalten.

# 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 
5

Es gibt auch eine native Heroku-Methode, dies jetzt zu tun. Heroku rollte eine Labs-Funktion log runtime metrics aus, die CPU-Auslastung und Speicherauslastungsinformationen in den Protokollierungsstrom einbringt. Diese Protokolle enthalten eine Quell-ID (z. B. "web.1") und eine eindeutige ID des Prüfpunkts, sodass Sie die Prüfpunkte unterscheiden können. Es sieht etwa so aus:

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 

dies auf einzuschalten, einfach auszuführen:

heroku labs:enable log-runtime-metrics 
heroku restart 
Verwandte Themen