2012-06-11 17 views
10

Çalıştığım uygulama, çoğu isteğin JSON nesneleriyle veya koleksiyonlarıyla yanıt veriyor. Bu yanıtları oluşturmak için Jbuilder kullanıyoruz. İşlenen veri miktarı oldukça büyüktür (çeşitli iç içe geçmiş yapılarda birkaç bin nesne - bir kez biçimlendirilmiş ve tamamen genişletildiğinde, tipik yanıt için 10,000 satırlık JSON değeri vardır). Bu işlem, NewRelic'e göre, toplam talep süresinin yaklaşık 1/3'ü - önemli bir zaman alıyor.Jbuilder ve Rails ile işleme performansının iyileştirilmesi 3

JBuilder'den mümkün olan en iyi performansı almamı sağlamaya yardımcı olacak bir kılavuz, ipuçlarını veya başka bir kaynağı arıyorum. Ayrıca Jbuilder vs RABL ya da benzer araçlar için mevcut performans karşılaştırmaları varsa merak ediyorum.

Düzeltme: Jbuilder performansı hakkında şikayet eden bir GitHub Issue buldum, ancak herkesin yaptığı tek öneri 'Jbuilder kullanmayın'. Aslında, biraz daha güçlü bir dil kullandılar, ancak 'da neden Jbuilder neden bu kadar yavaşsa, ne olursa olsun, etrafta dolaşmak için ne yapılabilir, ya da aynı iş için diğer araçların karşılaştırması nedir?

cevap

12

jbuilder verilerinizi içeren büyük bir karma oluşturur ve daha sonra json'a dönüştürmek için ActiveSupport::JSON'u kullanır. Aşağıdaki mikro kriter gösterir (eğer yüklü multijson ve yajl-yakut taşlar olduğundan emin olun) benim makinede

require 'benchmark' 
require 'active_support' 
require 'multi_json' 
sample = {menu: { 
    header: "SVG Viewer", 
    items: [ 
     {id: "Open"}, 
     {id: "OpenNew", label: "Open New"}, 
     nil, 
     {id: "ZoomIn", label: "Zoom In"}, 
     {id: "ZoomOut", label: "Zoom Out"}, 
     {id: "OriginalView", label: "Original View"}, 
     nil, 
     {id: "Quality"}, 
     {id: "Pause"}, 
     {id: "Mute"}, 
     nil, 
     {id: "Find", label: "Find..."}, 
     {id: "FindAgain", label: "Find Again"}, 
     {id: "Copy"}, 
     {id: "CopyAgain", label: "Copy Again"}, 
     {id: "CopySVG", label: "Copy SVG"}, 
     {id: "ViewSVG", label: "View SVG"}, 
     {id: "ViewSource", label: "View Source"}, 
     {id: "SaveAs", label: "Save As"}, 
     nil, 
     {id: "Help"}, 
     {id: "About", label: "About Adobe CVG Viewer..."} 
    ] 
}} 


MultiJson.engine = :yajl 
Benchmark.bmbm(5) do |x| 
    x.report 'activesupport' do 
    1000.times {ActiveSupport::JSON.encode(sample)} 
    end 
    x.report 'yajl' do 
    1000.times {MultiJson.encode(sample)} 
    end 
end 

bu örnek nesnesini kodlamak için

    user  system  total  real 
activesupport 1.050000 0.010000 1.060000 ( 1.068426) 
yajl   0.020000 0.000000 0.020000 ( 0.021169) 

yani üretir olarak daha hızlı json yayıcılar vardır 1000 kat aktif destek 1 saniyenin üzerinde bir saç aldı, MultiJson (yajl motorunu kullanarak) 21 ms aldı.

JBuilder, ActiveSupport :: JSON'u kullanmak için kodlanmıştır, ancak MultiJSON (json kitaplıkları arasında geçiş yapmanıza olanak tanıyan bir mücevher) önemsiz bir düşüştür ve zaten ActiveSupport'un bağımlılığıdır - benim fork of jbuilder'a bakın. Bir çekme isteği açtım, ancak o zamana kadar bu çatalı kullanmayı deneyebilirsiniz (ya da kendinizinkini yaratabilirsiniz - bu bir satır değişimi)

+0

MultiJson'a geçiş, 400ms'den yaklaşık 60 ms'lik bir kesinti yapıyor gibi görünüyor veya böylece, normal bir istek için görüntü oluştururken harcayabiliyoruz. Beklediğim devasa değişiklik değil, tek satırlık bir değişim için hiç de fena değil. Teşekkürler. – MrTheWalrus

+0

Evet. Bu. Mı. Harika. – maletor

+0

@Frederick: Bağlantıdaki değişikliklerin bir satırını görüyorum: - https://github.com/fcheung/jbuilder/commit/a58b355f68bc39b1fddf8b178f3844c5d4f65501 raylar ana ile birleştirildi, bu yüzden herhangi bir değişiklik yapmamız gerekmediğini tahmin ediyorum. Çıkarımın doğru olup olmadığını teyit edebilir misiniz? – boddhisattva

4

Rabl'e geçiş yapmayı ve bazı caching ekleyerek düşünün. Yuvalanmış yapılarda binlerce nesneye sahip olduğunuzdan, sonuçta elde ettiğiniz JSON'un bazı düğümleri kısmi olarak ve önbelleğe alınabilir - performans artışı çok büyük olabilir.

Bu Rabl performansından başka, JBuilder'in performansından biraz daha iyidir, ancak Rabl sözdizimini bazen kafa karıştırıcı buluyorum ve parçalı önbelleğe alma uygulandığında, JBuilder'e geçiyorum.

0

Daha önce belirtildiği gibi JBuilder bir karma oluşturur, daha sonra JSON karmasını seri hale getirir.

Önbelleğe alma ile aynı, ana karma ve önbelleğe alınmış karma hala JSON'a dönüştürülmesi gereken ana karma birleştirilir.

Benim çözümüm TurboStreamer idi. TurboStreamer bir IO/Stream/String'e doğrudan çıkış yapar, bu yüzden JBuilder'in serileştirme adımını atlar (ve ilk bakışta bu hala Rabl ve kullanıma bağlı olarak to_json için geçerlidir).

Bizim için bu, işleme süresinin & GC zamanını önemli ölçüde azaltmıştır (jbuilder'daki karma oluşturma nedeniyle) ve sonuçlarımızı elde ettikçe JSON'u akışa aktarmamızı sağlar. Dezavantajı TurboStreamer biraz daha ayrıntılı ve açık.

Performans Testi A (önbelleğe alma dahil):

Performans Testi B (çoğunlukla tüm önbelleğe alma):