2012-10-15 27 views
12

Có cách nào để tìm ra dung lượng bộ nhớ web dyno của heroku đang sử dụng không? Hãy nói rằng tôi muốn viết một công việc cào chạy theo định kỳ và kiểm tra việc sử dụng bộ nhớ của mỗi dyno. Làm thế nào tôi có thể làm điều này? Cảm ơn!Rails 3 + Heroku: Tìm hiểu cách sử dụng bộ nhớ của dyno

+1

Có một lý do không sử dụng New Relic? Giám sát> Dynos –

+1

Nó cho thấy sử dụng bộ nhớ tối thiểu, tối đa và trung bình của tất cả các dynos kết hợp, và không có cách nào (mà tôi biết) để lấy bộ nhớ của một dyno cụ thể – sauronnikko

Trả lời

3

Vì Heroku chạy trên một cá thể Amazon với Linux, bạn có thể sử dụng hệ thống tệp proc để nhận dữ liệu hệ thống thời gian chạy. Tệp /proc/<pid>/smaps chứa thông tin bộ nhớ về quá trình đang chạy và tất cả thư viện mà nó tải. Đối với quy trình cư trú, hãy thực hiện việc này:

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 

Cập nhật: Hệ thống tệp proc có nguồn tốt hơn, /proc/<pid>/status. Có một mục nhập VmRSS: cho tổng bộ nhớ cư trú và VmHWM: cho bộ nhớ thường trú cao nhất được sử dụng (dấu nước cao). Để biết thêm chi tiết về các trường này và các trường khác, hãy xem The Linux Kernel docs for the proc file system.

+0

Trên ngăn xếp Cedar của Heroku, nó trả về kích thước của thư viện đầu tiên , không phải là quá trình. Bạn có thể cần lặp lại và cộng tất cả các kích thước lại với nhau. – Sim

+0

Cảm ơn bạn đã làm rõ cho Cedar. –

6

Tôi lấy đề xuất từ ​​câu trả lời được chấp nhận và triển khai trình phân tích cú pháp hệ thống tập tin/proc với tập hợp sự khác biệt dựa trên ngưỡng &. Tôi thấy nó khá hữu ích trong việc gỡ lỗi một số vấn đề bộ nhớ Ruby 2.0 trên Heroku. Lấy code, cũng được bao gồm ở đây để thuận tiện.

# 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

Ngoài ra còn có một cách riêng để làm điều này ngay bây giờ. Heroku tung ra một phòng thí nghiệm tính năng log runtime metrics mà sẽ tiêm tải CPU và thông tin sử dụng bộ nhớ vào dòng ghi nhật ký. Các nhật ký này đi kèm với ID nguồn (ví dụ: "web.1") và ID duy nhất dyno, để bạn có thể cho biết các dynos tách biệt. Nó trông giống như sau:

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 

Để tắt chức năng này, chỉ cần chạy:

heroku labs:enable log-runtime-metrics 
heroku restart 
Các vấn đề liên quan