Bir bellek sızıntısı bulma neden Ruby
Benim Raylar bir bellek sızıntısı kodu olduğunu keşfettim, buldumnekod sızdırıyor ama değilnedenbu kaçaklar. Raylar gerektirmeyecek bir deneme durumu aşağı azalttım:
require 'csspool'
require 'ruby-mass'
def report
puts 'Memory ' `ps ax -o pid,rss | grep -E "^[[:space:]]*#{$$}"`.strip.split.map(&:to_i)[1].to_s 'KB'
Mass.print
end
report
# note I do not store the return value here
CSSPool::CSS::Document.parse(File.new('/home/jason/big.css'))
ObjectSpace.garbage_collect
sleep 1
report
ruby-mass sözde bellekteki tüm nesneleri görmemi sağlıyor. CSSPool CSS ayrıştırıcı racc dayanmaktadır. /home/jason/büyük.css a 1.5MB CSS file.
Bu çıkışları:
Memory 9264KB
==================================================
Objects within [] namespace
==================================================
String: 7261
RubyVM::InstructionSequence: 1151
Array: 562
Class: 313
Regexp: 181
Proc: 111
Encoding: 99
Gem::StubSpecification: 66
Gem::StubSpecification::StubLine: 60
Gem::Version: 60
Module: 31
Hash: 29
Gem::Requirement: 25
RubyVM::Env: 11
Gem::Specification: 8
Float: 7
Gem::Dependency: 7
Range: 4
Bignum: 3
IO: 3
Mutex: 3
Time: 3
Object: 2
ARGF.class: 1
Binding: 1
Complex: 1
Data: 1
Gem::PathSupport: 1
IOError: 1
MatchData: 1
Monitor: 1
NoMemoryError: 1
Process::Status: 1
Random: 1
RubyVM: 1
SystemStackError: 1
Thread: 1
ThreadGroup: 1
fatal: 1
==================================================
Memory 258860KB
==================================================
Objects within [] namespace
==================================================
String: 7456
RubyVM::InstructionSequence: 1151
Array: 564
Class: 313
Regexp: 181
Proc: 113
Encoding: 99
Gem::StubSpecification: 66
Gem::StubSpecification::StubLine: 60
Gem::Version: 60
Module: 31
Hash: 30
Gem::Requirement: 25
RubyVM::Env: 13
Gem::Specification: 8
Float: 7
Gem::Dependency: 7
Range: 4
Bignum: 3
IO: 3
Mutex: 3
Time: 3
Object: 2
ARGF.class: 1
Binding: 1
Complex: 1
Data: 1
Gem::PathSupport: 1
IOError: 1
MatchData: 1
Monitor: 1
NoMemoryError: 1
Process::Status: 1
Random: 1
RubyVM: 1
SystemStackError: 1
Thread: 1
ThreadGroup: 1
fatal: 1
==================================================
Bellek görebilirsinizyol. Bazı sayaçlar yukarı gitmek, ama hiçbir nesne CSSPool için özel hediye. Ruby kitle "" gibi referansları olan nesneleri kontrol yöntemi: . ındex kullandım
Mass.index.each do |k,v|
v.each do |id|
refs = Mass.references(Mass[id])
puts refs if !refs.empty?
end
end
Fakat yine de, bu bana bir şey CSSPool, gem bilgi sadece ilgili ve bu tür vermez.
Ayrıca "GC.çıkartmaya çalıştım"... . stat
puts GC.stat
CSSPool::CSS::Document.parse(File.new('/home/jason/big.css'))
ObjectSpace.garbage_collect
sleep 1
puts GC.stat
Sonuç:
{:count=>4, :heap_used=>126, :heap_length=>138, :heap_increment=>12, :heap_live_num=>50924, :heap_free_num=>24595, :heap_final_num=>0, :total_allocated_object=>86030, :total_freed_object=>35106}
{:count=>16, :heap_used=>6039, :heap_length=>12933, :heap_increment=>3841, :heap_live_num=>13369, :heap_free_num=>2443302, :heap_final_num=>0, :total_allocated_object=>3771675, :total_freed_object=>3758306}
Anladığım kadarıyla, bir nesne başvurulan ve çöp toplama olursa, o zaman o nesnenin bellekten temizlenmelidir. Ama burada olan şey görünmüyor.
Ayrıca C-düzey bellek sızıntısı hakkında çok şey okudum, ve CSSPool kullanır C kodu kullanan Racc beri, bu bir olasılık olduğunu düşünüyorum. Valgrind ile benim kod çalıştırmak var:
valgrind --partial-loads-ok=yes --undef-value-errors=no --leak-check=full --fullpath-after= ruby leak.rb 2> valgrind.txt
Sonuçlar here. Eğer bu C-düzey bir sızıntı teyit emin değilim, Ruby Valgrind anlamayan bellek ile bir şeyler yapıyor da okudum.
Sürüm:
- Ruby 2.0.0-p247 (bu benim Raylar app çalışır)
- Ruby-p392-ref 1.9.3 (ruby-kütle ile test için)
- ruby kitle 0.1.3
- CSSPool here 4.0.0
- Otomotiv-6.4 ve Ubuntu 13.10
CEVAP
Giriyorsunuz gibi görünüyorKayıp Dünyaburada. Sorun c-bağları racc
da olduğunu sanmıyorum.
Ruby bellek yönetimi hem zarif hem de hantal. Nesneler (RVALUE
s adlı) sözde saklaryığınlarıyaklaşık 16KB büyüklüğünde. , RVALUE
düşük bir seviyede olur c-bir yapı, union
farklı standart yakut nesne temsilleri içeren.
Böylece, kümeler *19 Ebat 40'tan fazla bayt olmayan nesneleri saklamak. *, , * Array
Hash
20 vb gibi nesneler için. bu küçük nesneler yığını uyum anlamına gelir, ama bir eşik ulaşır ulaşmaz, Ruby kümeler dışında fazladan bir bellek ayrılmış olur.
Bu ekstra bellek esnektir; bir nesne GC çiğnenmiş oldu en kısa sürede serbest bırakılacaktır.big_string
ile deneme durumu Yukarı-Aşağı davranış: bellek gösterir
def report
puts 'Memory ' `ps ax -o pid,rss | grep -E "^[[:space:]]*#{$$}"`
.strip.split.map(&:to_i)[1].to_s 'KB'
end
report
big_var = " " * 10000000
report
big_var = nil
report
ObjectSpace.garbage_collect
sleep 1
report
# ⇒ Memory 11788KB
# ⇒ Memory 65188KB
# ⇒ Memory 65188KB
# ⇒ Memory 11788KB
Ama kümeler (GC[:heap_length]
) kendilerinideğildir yayımladıgeri OS için kazanılmış bir kez. Bak, senin test çalışmasına monoton bir değişiklik yapalım:
- big_var = " " * 10000000
big_var = 1_000_000.times.map(&:to_s)
Ve iÅŸte, sihir:
# ⇒ Memory 11788KB
# ⇒ Memory 65188KB
# ⇒ Memory 65188KB
# ⇒ Memory 57448KB
Bellek dizisi ben her öge-çünkü artık OS, piyasaya geri döndütakım elbiseRVALUE
boyutu vesaklanırruby öbek.
Eğer GC çalıştırıldı sonra GC.stat
çıktısını inceleyin. eğer GC[:heap_used]
değeri beklendiği gibi azalma olduğunu göreceksiniz. Ruby şimdi boş yığınları, bir sürü hazır.
Bu özetliyor:Sanmıyorum, c
kod sızdırıyor. Sorun css
senin büyük resmin base64 gösterimi içinde olduğunu düşünüyorum. İçinde ayrıştırıcı neler olduğunu hiçbir ipucu var, ama büyük dize ruby öbek sayısını artırmak için zorlar gibi görünüyor.
Umarım yardımcı olur.
Neden 'yeni' neden bellek sı...
Bulma Krom bellek sızıntısı JavaScript...
Neden bir WordPress kullanmak çok kötü...
Neden olabilir .NET bellek sızıntısı v...
raylar üzerinde ruby/ruby bellek sızın...