2016-03-29 11 views
5

libxml-ruby gem kullanarak 500 MB XML dosyasını ayrıştıran bir kod parçam var. Ne bana şaşırtıcı olan, bu kod çalışır sezgilere görünüyor GC özürlü ile yavaş. Sebebi ne olabilir? Çok fazla bellek kullanıyorum ve sistem değişmiyor.Bu XML'in Ruby kodunu ayrıştırması neden GC devre dışıyken daha yavaş çalışıyor?

ruby  gc on gc off 
2.2.0 16.93s 18.81s 
2.1.5 16.22s 18.58s 
2.0.0 17.63s 17.99s 

Neden çöp toplayıcı devre dışı bırakın:

require 'xml' 

#GC.disable 

@reader = XML::Reader.file('books.xml', :options => XML::Parser::Options::NOBLANKS) 

@reader.read 
@reader.read 

while @reader.name == 'book' 
    book_id = @reader.get_attribute('id') 
    @reader.read 

    until @reader.name == 'book' && @reader.node_type == XML::Reader::TYPE_END_ELEMENT 
    case @reader.name 
    when 'author' 
     author = @reader.read_string 
    when 'title' 
     title = @reader.read_string 
    when 'genre' 
     genre = @reader.read_string 
    when 'price' 
     price = @reader.read_string 
    when 'publish_date' 
     publish_date = @reader.read_string 
    when 'description' 
     description = @reader.read_string 
    end 
    @reader.next 
    end 

    @reader.read  

end 
@reader.close 

İşte aldığım sonuçlar nelerdir? Ruby Performance Optimization kitabında okudum, Ruby'nin yavaş olduğunu, çünkü programcıların bellek tüketimini düşünmediklerini, bu da çöp toplayıcısının çok fazla yürütme süresi kullanmasını sağlıyor. Böylelikle, sistemin kapatılmaması koşuluyla, GC'nin kapatılması anında bir şeyleri hızlandıracaktır (elbette bellek kullanım maliyetine bağlı olarak).

benim XML ayrıştırma modülü geliştirilebilir görmek istedim, bu yüzden bu soruna götürdü GC, devre dışı bırakarak onunla denemeye başladı. GC devre dışıyken önemli bir hızlanma bekledim, bunun yerine tam tersini aldım. Farkların çok büyük olmadığını biliyorum, ama yine de bu benim için garip.

libxml-ruby gem, kaputun altında yerel bir C LibXML uygulaması kullanıyor - nedeni bu olabilir mi?

elle bazı Microsoft belgelerine indirilen books.xml numuneyi multiplicated edilir kullanılan dosya:

<catalog> 
<book id="bk101"> 
    <author>John Doe</author> 
    <title>XML for dummies</title> 
    <genre>Computer</genre> 
    <price>44.95</price> 
    <publish_date>2000-10-01</publish_date> 
    <description>Some description</description> 
</book> 
.... 
</catalog> 

Benim kurulumu: OS X Yosemite, Intel Core i5 2.6 GHz, RAM 16GB.

Önerileriniz için teşekkür ederiz. İşletim sistemini unutuyorsunuz

+0

@engineersmnky, nasıl daha hızlı yapılacağını sorarsa, kod incelemesine değil, buraya aittir. Tüm bunlarla ilgili yardım istiyorsa, oraya gitmeli. – Riker

+0

@engineersmnky "Nedeni ne olabilir?Çok fazla bellek kullanıyorum ve sistem değişmiyor. " – Riker

+1

@engineersmnky" Aşağıdaki kodun herhangi bir veya tüm yönleri hakkında geri bildirim istiyorum mu? " Geri Bildirim Ver Daha fazla bilgi –

cevap

1

- Eğer MRG sürecinde engelli GC ettik ama Linux/Unix kernel üzerinde herhangi bir kontrolü var ve bu sizin MR uygulaması için bellek ayırır nasıl.

Aslında, GC devre dışı bırakarak önemli ölçüde programı sürekli çekirdekten daha fazla RAM talep gerekeceğini büyük olasılıkla yapım uygulamanın davranışını hamstrung inanıyoruz. Bu, çekirdeği veya hafızayı size ayırabileceği için, çekirdeğin bir tür ek yükünü içerecektir.

Kaynağınız verileri MRG programın bellek ayak izi içine okuduğunuz 500 mb xml dosyası, düğümün düğüm vardır. Muhtemelen MRI işleminiz, işlendiği sırada birkaç GB veri tüketir; ve ana okuma bloğunuzdaki değerlerin hiçbiri, her yinelemeden sonra atılmaz - sadece bellekte takılırlar, ve son olarak uygulamanız çıktığında ve bellek işletim sistemine geri verildiğinde temizlenir.

GC, bunu yönetmek için yerinde; Uygulamanızın kesinlikle gerekli olmadıkça çekirdeğinden ek bellek istemesini engellemeye ve uygulamanızın akılda tahsis edilen bellek içinde "yeterince iyi" çalışmasına izin vermesi amaçlanmıştır.

Yani dürüst devre dışı bırakılmış GC ile yavaşlama görmeye şaşırmıyorum. Söyleyeceğiniz şey, karşılaştırmalarınız sırasında kutunun yük ortalaması ve takas kullanımıdır.

+0

OS ayırma ek yükü ile ilgili öneriniz için teşekkürler. akılda: – mjkpl

+0

Muhtemelen haklısınız.Onun sürekli bir şekilde küçük artışlarla daha fazla bellek ayırdığını görebiliyorum.Kesinlikle ispatlamak için bir yol aradım. Başlangıçta büyük miktarda bellek bulun (Java'da -Xmx' gibi), böylece yürütme sırasında herhangi bir zaman harcamanız gerekmeyecek. Ama görünüşe göre Ruby'de mümkün değil. – mjkpl

İlgili konular