2016-05-16 17 views
8

Bir SVG haritanız var ve veri için yapılan anketler, haritadaki renkleri değiştirerek günceller. Yeni rengin solması için bir geçiş kullanmazsam her şey yolunda gider. Ardından, sekme yavaşça çökerene kadar daha fazla bellek harcar. Ben Krom (49) ve Linux üzerinde Firefox (45) 'de denedimSürekli olarak d3 geçişi uygulanıyorken bellek sızıntısı

var size = 500; 
var num = 25; 
var boxSize = size/num; 

function color(d) { 
    return '#' + Math.random().toString(16).slice(2,8); 
} 

var svg = d3.select('body') 
    .append("svg") 
    .attr("width", size) 
    .attr("height", size); 

var squares = svg.selectAll(".square") 
    .data(d3.range(num * num)) 
    .enter().append("rect") 
    .attr("class", "square") 
    .attr("width", boxSize) 
    .attr("height", boxSize) 
    .attr("x", function (d) { return boxSize * (d % num);}) 
    .attr("y", function (d) { return boxSize * Math.floor(d/num); }) 
    .style("fill", color); 

function shuffleColors() { 
    squares.interrupt().transition().duration(500).style("fill", color); 
    timer = setTimeout(shuffleColors, 1000); 
} 

var timer = setTimeout(shuffleColors, 1000); 

https://plnkr.co/edit/p71QmO

:

Ben aynı davranışı gösteren bir basitleştirilmiş bir örnek yaptık. Eskiden daha hızlı patlar gibi görünüyor, ama her ikisinde de bir sorun. Aynı zamanda bellek profilerinde görünmez, ancak yaklaşık: bellek sekmenin büyürken olduğunu gösterir.

Dokümantasyondaki anlayışım, bir seçime geçiş eklemenin, bir önceki geçişi (boş ad için de dahil olmak üzere) bir önceki geçişin yerini almasıdır, ancak hipotezim, geçişi gerçekleştirmek için oluşturulan işlevlerin gerçekten atılmamasıdır. dışarı. Ancak, bunu doğrulamak veya sorunu çözmek için onlara ulaşmayı başaramadım. Yani

, iki bölümden oluşan soru:

  1. mi d3 geçişler doğru kullanımı, ya da ben gidiyorum ne yapacağını daha doğru bir yolu var mı?
  2. Geçişi düzgün kullanıyorum, bellek sızıntısını durdurmak için nasıl alabilirim?

DÜZENLEME: Blindman67 dan Başına yorum

  1. , ben setTimeout kullanmak ve biraz daha küçük olacak şekilde değiştirildi. Benzetmeye çalıştığım orijinal, daha küçük ve yavaştır, ama kesinlikle daha büyük büyümek saatler alır, bu yüzden onu hızlandırmaya çalışıyordum. Bu sürüm hala en azından benim için Chromium'da büyüyor görünmektedir.
  2. d3_selectionPrototype.transition'un her defasında bir artırım kimliğine sahip yeni bir d3_transition yaptıklarını gözlemledim, ancak eskisi çöp toplanırsa sorun olmaz. Ve hala korunup tutulmadığını veya neden korunduğunu gösteremiyorum.
+5

Shuffle Renkler işlevinize bir hata ayıklayıcı anahtar kelime ekledim ve bunu D3 koduna ekledim. Çağrı kesintisinde yaptığı ilk şey, 1600 kesintinin bir listesini oluşturmaya başlamıştı, Her bir kareyi ayrı bir varlık olarak ele alıyor. Sorun daha açık olduğu için daha derine inmedim, büyük parçalar halinde hafızayı çiğniyorsunuz, GC yavaşlamaya başladığında yavaş yavaş setInterval'ı koyacaktır, bu sadece bir kez çarpışmayı bekliyor. SetTimeout'u kullanın ve işiniz bittikten sonra bir sonraki karıştırmaya başlayın. Hafıza sızdırmadığı için çağrı yığınının taştığını görüyorsun – Blindman67

+0

Sadece 'interrupt() 'hakkında aynı şeyi söylemek üzereydim. –

+0

Olası çoğaltılabilir [D3 geçişlerini kullanma bellek sızmasına neden olur] (https://stackoverflow.com/questions/26735417/using-d3-transitions-causes-memory-leak) – Fraser

cevap

0

ben tam burada, bu parçayı yapmak zorunda eminim:

function shuffleColors() { 
    squares.interrupt().transition().duration(500).style("fill", color); 
    timer = setTimeout(shuffleColors, 1000); 
} 

var timer = setTimeout(shuffleColors, 1000); 

işlevi shuffleColors() arasam, aslında bir baz durumda olmayan bir yineleme döngü yaratarak, kendisini yeniden çağırır. Hemen patlamamasının nedeni, fonksiyonun her çağrısının 1000 ms gecikmesidir, ancak 'un bitmesi, setTimeout()'un çağrılmasından daha uzun sürecektir. Yani her 1000 ms olarak adlandırsanız bile, bazı renk değişikliklerinin işlenmesi için daha fazla zaman gerektirebileceğinden, bir şekilde biriktirilebilir.

Asenkron JavaScript'in nasıl olduğunu bilerek teknik olarak yapılmasa da, bir rolü olabilir. Bunun yerine bu yapıyor ve sonuçları rapor veriyor öneririz olacaktır: Eğer herhangi bir noktada gerekirse

function shuffleColors() { 
    squares.interrupt().transition().duration(500).style("fill", color); 
} 

var timer = setInterval(shuffleColors, 1000); 

Ayrıca clearInterval(timer) çağırabilir. setInterval(), setTimeout()'u uygulamanızın sebebi için oluşturuldu.

Düzenleme: Bu, renk değişikliğinin bitmesini beklediğiniz gibi tamamen çalışmayabilir, ancak en azından temiz bir yaklaşım olur. Renk değişiminin tamamlanmasını beklemek için bir çeşit wait() işlevini uygulayabilirsiniz.

Vektör (SVG) görüntüleri hafif olmasına rağmen, sürekli olarak renkleri değiştirmek için gereken işleme miktarı veya JPEG gibi bir görüntünün kodunun çözülmesiyle karşılaştırıldığında çok daha büyük bir şey.

Orijinal görüntü boyutunu çok daha küçük hale getirip daha sonra çözünürlüğünüze genişletirseniz daha iyi sonuçlar alabilirsiniz. Bir 100x100 kanvas SVG yapabilir ve 2000x2000 veya bir şeye genişletebilirsiniz, böylelikle büyük bir resim çizmeniz gerekmez.