HTML5 Uygulamanızın performansını iyileştirme

Giriş

HTML5 bize web uygulamalarının görselliğini iyileştirmek için harika araçlar sunuyor. Bu durum özellikle animasyonlar için geçerlidir. Ancak bu yeni güçle birlikte yeni zorluklar da beraberinde geliyor. Aslında bu zorluklar o kadar da yeni değildir ve masa başındaki komşunuz Flash programcısına geçmişte benzer durumları nasıl aştığını sormak bazen mantıklı olabilir.

Yine de, animasyonla çalıştığınızda, kullanıcıların bu animasyonların yumuşak olduğunu algılamaları son derece önemli hale gelir. Gerçekte animasyonlardaki pürüzsüzlüğün, saniyedeki kare sayısını herhangi bir bilişsel eşiğin üzerine çıkararak oluşturulamayacağını anlamamız gerekir. Ne yazık ki beynimiz bundan daha akıllı. Saniyede 30 animasyon karesinin (fps) ortada yalnızca birkaç kare atlandığında 60 kare/saniyeden çok daha iyi olduğunu öğreneceksiniz. İnsanlar pürüzlülükten nefret eder.

Bu makalede, kendi uygulamanızın deneyimini iyileştirmek için kullanabileceğiniz araç ve teknikleri sunmaya çalışacağız.

Strateji

Hiçbir şekilde sizi HTML5 ile müthiş, şaşırtıcı görsel uygulamalar oluşturmaktan vazgeçirmek istemiyoruz.

Performansın biraz daha iyi olabileceğini gördüğünüzde buraya geri dönüp uygulamanızın öğelerini nasıl iyileştirebileceğinizle ilgili bilgi alabilirsiniz. Elbette, bazı şeyleri en başta doğru şekilde yapmanıza yardımcı olabilir. Ancak bunun üretkenliğinize engel olmasına izin vermeyin.

HTML5 ile görsel kalite++

Donanım Hızlandırma

Donanım hızlandırma, tarayıcıda genel oluşturma performansı açısından önemli bir aşamadır. Genel şema, normalde ana CPU tarafından hesaplanacak görevleri bilgisayarınızın grafik adaptöründeki grafik işleme birimine (GPU) boşaltmaktır. Bu yöntem performansta büyük artış sağlayabilir ve mobil cihazlarda kaynak tüketimini azaltabilir.

Dokümanınızın bu yönleri GPU tarafından hızlandırılabilir

  • Genel düzen birleştirme
  • CSS3 geçişleri
  • CSS3 3D dönüşümleri
  • Tuval Çizimi
  • WebGL 3D Çizim

Tuval ve WebGL hızlandırmalı olmak, sizin uygulamanız için geçerli olmayabilecek özel amaçlı özellikler olsa da ilk üç özellik hemen hemen her uygulamanın daha hızlı çalışmasına yardımcı olabilir.

Neleri hızlandırabilir?

GPU hızlandırması, iyi tanımlanmış ve belirli görevleri özel amaçlı donanımlara boşaltarak yapılır. Genel şema, dokümanınızın, sayfanızın hızlandırılmış yönlerine bağlı olmayan birden çok "katmana" bölünmüş olmasıdır. Bu katmanlar, geleneksel oluşturma ardışık düzeni kullanılarak oluşturulur. GPU daha sonra, çalışırken hızlandırılabilecek "efektleri" uygulayarak katmanları tek bir sayfada birleştirmek için kullanılır. Olası bir sonuç, ekranda canlandırılan bir nesnenin, animasyon gerçekleşirken sayfanın tek bir "düzenlenmesini" gerektirmemesidir.

Buradan çıkarmanız gereken şey, oluşturma motorunun GPU hızlandırma sihrini ne zaman uygulayabileceğini belirlemesini kolaylaştırmanızdır. Aşağıdaki örneği inceleyin:

Bu şekilde de tarayıcı, bir insan tarafından yumuşak animasyon olarak algılanması gereken bir şey yaptığınızı gerçekten bilmez. Bunun yerine CSS3 geçişlerini kullanarak aynı görsel görünümü elde ettiğinizde ne olacağını düşünün:

Tarayıcının bu animasyonu nasıl uyguladığı, geliştiriciden tamamen gizlidir. Bu da, tarayıcının tanımlanan hedefe ulaşmak için GPU hızlandırması gibi hileler uygulayabileceği anlamına gelir.

Chrome'un GPU hızlandırmalı hata ayıklama işlemine yardımcı olması için iki kullanışlı komut satırı işareti vardır:

  1. --show-composited-layer-borders, GPU düzeyinde değiştirilen öğelerin çevresinde kırmızı bir kenarlık gösterir. İşlemlerinizin GPU katmanı içinde gerçekleştiğini doğrulamak için idealdir.
  2. --show-paint-rects GPU dışı tüm değişiklikler boyanır ve bu, yeniden boyanan tüm alanların etrafına açık bir kenarlık oluşturur. Tarayıcının boyama alanlarını optimize ederken nasıl çalıştığını görebilirsiniz.

Safari burada açıklanan benzer çalışma zamanı işaretlerine sahiptir.

CSS3 Geçişleri

CSS Geçişleri, stil animasyonunu herkes için vazgeçilmez hale getirir ama aynı zamanda akıllı bir performans özelliğidir. CSS geçişi tarayıcı tarafından yönetildiğinden animasyonun doğruluğu büyük ölçüde iyileştirilebilir ve çoğu durumda donanım hızlandırılır. Şu anda WebKit'te (Chrome, Safari, iOS) donanım hızlandırmalı CSS dönüşümleri kullanılsa da diğer tarayıcı ve platformlarda da kullanılmaya başlanır.

Bunu güçlü kombinasyonlara dönüştürmek için transitionEnd etkinliklerini kullanabilirsiniz. Ancak şu anda, desteklenen tüm geçiş sonu etkinliklerini yakalamak webkitTransitionEnd transitionend oTransitionEnd izlemek anlamına geliyor.

Birçok kitaplıkta, mevcut olması halinde geçişlerden yararlanan ve aksi halde standart DOM stili animasyona geri dönen animasyon API'leri kullanıma sunulmuştur. scripty2, YUI geçişi, jQuery iyileştirilmiş.

CSS3 Çeviri

Daha önce bir öğenin x/y konumunu canlandırdığınıza eminim. Satır içi stilin sol ve üst özelliklerini değiştirmiş olabilirsiniz. 2D dönüştürmelerle bu davranışı tekrarlamak için translate() işlevini kullanabiliriz.

Mümkün olan en iyi şeyi kullanmak için bunu DOM animasyonuyla

<div style="position:relative; height:120px;" class="hwaccel">

  <div style="padding:5px; width:100px; height:100px; background:papayaWhip;
              position:absolute;" id="box">
  </div>
</div>

<script>
document.querySelector('#box').addEventListener('click', moveIt, false);

function moveIt(evt) {
  var elem = evt.target;

  if (Modernizr.csstransforms && Modernizr.csstransitions) {
    // vendor prefixes omitted here for brevity
    elem.style.transition = 'all 3s ease-out';
    elem.style.transform = 'translateX(600px)';

  } else {
    // if an older browser, fall back to jQuery animate
    jQuery(elem).animate({ 'left': '600px'}, 3000);
  }
}
</script>

CSS 2D dönüşümleri ve CSS geçişleri için özellik testi yapmak üzere Modernizr'ı kullanıyoruz. Kullanıyorsak konumu değiştirmek için çeviriyi kullanacağız. Bu animasyon bir geçiş kullanılarak gösteriliyorsa, tarayıcının donanım tarafından bunu hızlandırma olasılığı yüksektir. Tarayıcıya doğru yönde bir ilerleme daha sağlamak için yukarıdan "sihirli CSS madde işareti"ni kullanacağız.

Tarayıcımız daha az yetenekliyse öğemizi taşımak için jQuery'ye döneriz. Tüm bu süreci otomatik hale getirmek için Louis-Remi Babe'in jQuery Transform polyfill eklentisini kullanabilirsiniz.

window.requestAnimationFrame

requestAnimationFrame, Mozilla tarafından kullanıma sunulmuş ve DOM/CSS tabanlı veya <canvas> ya da WebGL'de olan animasyonları çalıştırmanız için size yerel bir API sağlamak amacıyla WebKit tarafından geliştirilmiştir. Tarayıcı, eşzamanlı animasyonları tek bir yeniden düzenleme ve yeniden boyama döngüsünde optimize ederek daha yüksek kaliteli animasyonlar elde edebilir. Örneğin, CSS geçişleri veya SVG SMIL ile senkronize edilmiş JS tabanlı animasyonlar. Ayrıca, animasyon döngüsünü görünmeyen bir sekmede çalıştırıyorsanız tarayıcı çalıştırmaya devam etmez. Bu da daha az CPU, GPU ve bellek kullanımı nedeniyle pil ömrünün çok daha uzun sürmesine neden olur.

requestAnimationFrame ürününün nasıl ve neden kullanıldığı hakkında daha fazla bilgi için Paul Ireland'ın requestAnimationFrame for smart animating (Akıllı animasyon için requestAnimationFrame) başlıklı makalesini görüntüleyin.

Profil oluşturma

Uygulamanızın hızının iyileştirilebileceğini fark ettiğinizde, optimizasyonların en fazla faydayı sağlayabileceği yerleri bulmak için profil çıkarma işlemini derinlemesine inceleyebilirsiniz. Optimizasyonlar çoğu zaman kaynak kodunuzun bakımını olumsuz yönde etkiler ve bu nedenle yalnızca gerektiğinde uygulanmalıdır. Profil oluşturma, performansları iyileştirildiğinde kodunuzun hangi bölümlerinin en büyük avantajları sağlayacağını belirtir.

JavaScript Profili Oluşturma

JavaScript profil oluşturucuları, her bir işlevin başlangıcından sonuna kadar yürütmek için gereken süreyi ölçerek JavaScript işlevi düzeyinde uygulamanızın performansına ilişkin bir genel bakış sağlar.

Bir işlevin brüt yürütme süresi, bir işlevi yukarıdan aşağıya doğru yürütmek için gereken toplam süredir. Net yürütme süresi, brüt yürütme süresinden fonksiyondan çağrılan işlevleri yürütmek için geçen süreden çıkarılarak bulunur.

Bazı işlevler diğerlerinden daha sık çağrılır. Profiler'lar genellikle tüm çağrıların çalıştırılması için gereken sürenin yanı sıra ortalama, minimum ve maksimum yürütme süresini de bildirir.

Daha fazla bilgi için profil oluşturma ile ilgili Chrome Geliştirici Araçları dokümanlarına göz atın.

DOM

JavaScript performansı, uygulamanızın ne kadar akıcı ve duyarlı olacağı konusunda güçlü bir etkiye sahiptir. JavaScript profilcilerinin JavaScript'inizin yürütme süresini ölçmekle birlikte, DOM işlemleri için harcanan süreyi de dolaylı olarak ölçtüklerini unutmamanız önemlidir. Performans sorunlarınızın merkezinde genellikle bu DOM işlemleri yer alır.

function drawArray(array) {
  for(var i = 0; i < array.length; i++) {
    document.getElementById('test').innerHTML += array[i]; // No good :(
  }
}

Örneğin yukarıdaki kodda, gerçek JavaScript'i yürütmek için neredeyse hiç zaman harcanmaz. DOM ile gereksiz bir şekilde etkileşim kurduğundan,drawArray işlevi yine de profillerinizde görünebilir.

İpuçları ve Püf Noktaları

Anonim İşlevler

Anonim işlevler, yapısı gereği profil oluşturucuda gösterilebilecek adlara sahip olmadıklarından kolayca profillenemez. Bu sorunu çözmek için iki yöntem vardır:

$('.stuff').each(function() { ... });

yeniden yaz:

$('.stuff').each(function workOnStuff() { ... });

JavaScript'in adlandırma işlevi ifadelerini desteklediği yaygın bir şekilde bilinmemektedir. Bu sayede profil oluşturucuda mükemmel bir şekilde görüntülenebilirler. Bu çözümle ilgili bir sorun var: Adlandırılmış ifade, işlev adını mevcut sözlük kapsamına yerleştiriyor. Bu, diğer simgelerin bozulmasına neden olabilir. Bu yüzden dikkatli olun.

Uzun işlevlerin profilini oluşturma

Uzun bir göreviniz olduğunu ve performans sorunlarınızın küçük bir parçasının bu işlevden kaynaklanmış olabileceğinden şüphelendiğinizi düşünün. Sorunun hangi bölümde olduğunu öğrenmenin iki yolu vardır:

  1. Doğru yöntem: Kodunuzu uzun işlevler içerecek şekilde yeniden düzenleyin.
  2. Kötü niyetli şeyleri elden çıkarma yöntemi: İfadeleri, adlandırılmış kendiliğinden çalışan işlevler biçiminde kodunuza ekleyin. Biraz dikkatli olursanız bu, anlamları değiştirmez ve işlevinizin bazı bölümlerinin profil oluşturucuda ayrı işlevler olarak görünmesine neden olur: js function myLongFunction() { ... (function doAPartOfTheWork() { ... })(); ... } Profil çıkarma işlemini tamamladıktan sonra bu ekstra işlevleri kaldırmayı unutmayın. Hatta bunları, kodunuzu yeniden düzenlemek için başlangıç noktası olarak da kullanabilirsiniz.

DOM Profili Oluşturma

En son Chrome Web Denetleyicisi geliştirme araçları, tarayıcının gerçekleştirdiği alt düzey işlemlerin zaman çizelgesini gösteren yeni "Zaman Çizelgesi Görünümü"nü içerir. Bu bilgileri, DOM işlemlerinizi optimize etmek için kullanabilirsiniz. Kodunuz çalışırken tarayıcının yapması gereken "eylemlerin" sayısını azaltmayı hedeflemelisiniz.

Zaman çizelgesi görünümü, muazzam miktarda bilgi oluşturabilir. Bu nedenle, bağımsız olarak yürütebileceğiniz minimum test durumu oluşturmaya çalışmalısınız.

DOM Profili Oluşturma

Yukarıdaki resimde, çok basit bir komut dosyasının zaman çizelgesi görünümünün çıktısı gösterilmektedir. Soldaki bölmede, tarayıcı tarafından gerçekleştirilen işlemler kronik sırayla gösterilirken, sağ bölmedeki zaman çizelgesi tek bir işlem tarafından tüketilen gerçek süreyi gösterir.

Zaman çizelgesi görünümü hakkında daha fazla bilgi edinin. Internet Explorer'da profil oluşturmak için kullanılabilecek alternatif bir araç da DynaTrace Ajax Edition'dır.

Profil Oluşturma Stratejileri

Yönleri tek tek seçin

Uygulamanızın profilini çıkarmak istediğinizde, yavaşlığı tetikleyebilecek özelliklerini mümkün olduğunca yakından belirlemeye çalışın. Ardından, kodunuzun yalnızca uygulamanızın bu yönleriyle ilgili bölümlerini yürüten bir profil çalıştırması yapmayı deneyin. Bu, gerçek sorununuzla ilgili olmayan kod yollarıyla iç içe geçmediğinden profil oluşturma verilerinin yorumlanmasını kolaylaştırır. Aşağıdakiler, uygulamanızın bağımsız yönleri için iyi birer örnek olabilir:

  1. Başlatma süresi (profil oluşturucuyu etkinleştirme, uygulamayı yeniden yükleme, başlatma tamamlanana kadar bekleme, profil oluşturucuyu durdurma.
  2. Bir düğmeyi ve sonraki animasyonu tıklayın (profil oluşturucuyu başlatma, düğmeyi tıklama, animasyon tamamlanana kadar bekleme, profil oluşturucuyu durdurma).
GUI Profili Oluşturma

Bir GUI programında uygulamanızın yalnızca doğru kısmını yürütmek, 3D motorunuzun ışın izleyicisini optimize etmekten daha zor olabilir. Örneğin, bir düğmeyi tıkladığınızda gerçekleşen şeylerin profilini çıkarmak istediğinizde, fare imlecini üzerine alma işlemi boyunca, sonuçlarınızın daha az kesin olmasına neden olan alakasız fareyle üzerine gelme etkinlikleri tetikleyebilirsiniz. Bundan kaçınmaya çalışın :)

Programlı Arayüz

Hata ayıklayıcıyı etkinleştirmek için programatik bir arayüz de vardır. Bu sayede profil oluşturma işleminin ne zaman başlayacağı ve ne zaman biteceği üzerinde hassas bir kontrole sahip olursunuz.

Şununla profil çıkarmaya başlayın:

console.profile()

Şununla profil oluşturmayı durdur:

console.profileEnd()

Tekrarlanabilirlik

Profil oluşturma işlemi yaparken, sonuçlarınızı gerçekten yeniden oluşturabileceğinizden emin olun. Ancak o zaman optimizasyonlarınızın gerçekten iyileştirmeler yapıp yapmadığını anlayabilirsiniz. Ayrıca, işlev düzeyinde profil oluşturma işlemi bilgisayarınızın tamamı bağlamında da yapılır. Bu kesin bir bilim değildir. Bağımsız profil çalıştırmaları, bilgisayarınızda meydana gelen diğer pek çok şeyden etkilenebilir:

  1. Kendi uygulamanızda, siz başka bir şeyi ölçerken tetiklenen alakasız bir zamanlayıcı.
  2. İşini yapan çöp toplayıcı.
  3. Tarayıcınızda, aynı işletim iş parçacığında yoğun çalışan başka bir sekme.
  4. Bilgisayarınızda CPU'yu kullanan başka bir program, bu nedenle uygulamanızı yavaşlatır.
  5. Dünyanın yerçekimi alanındaki ani değişimler.

Ayrıca, tek bir profil oluşturma oturumunda aynı kod yolunu birden çok kez çalıştırmak da mantıklıdır. Böylece yukarıdaki faktörlerin etkisini azaltıp yavaş kısımlar daha da belirgin bir şekilde öne çıkabilir.

Ölçün, iyileştirin, ölçün

Programınızda yavaş bir nokta tespit ettiğinizde, yürütme davranışını iyileştirmenin yollarını bulmaya çalışın. Kodunuzu değiştirdikten sonra profili tekrar oluşturun. Sonuçtan memnunsanız devam edin. Bir iyileşme görmüyorsanız büyük olasılıkla değişikliğinizi geri çekmeli ve "yaratıcı olmadığı için" olduğu gibi bırakmamalısınız.

Optimizasyon Stratejileri

DOM etkileşimini en aza indirin

DOM etkileşiminin en aza indirilmesi, web istemcisi uygulamalarının hızını artırmak için yaygın olarak kullanılır. JavaScript motorlarının hızı büyük bir hızla artmış olsa da DOM'a erişim aynı hızda olmamıştır. Bu, aynı zamanda, hiçbir zaman yaşanmayacak çok pratik nedenlerden dolayı da geçerlidir (bir şeyleri ekranda düzenlemek ve çizmek gibi işler sadece zaman alır).

DOM Düğümlerini Önbellek

DOM'den bir düğüm veya düğüm listesi aldığınızda, bunları sonraki bir hesaplamada (hatta yalnızca bir sonraki döngü yinelemesinde) yeniden kullanıp kullanamayacağınızı düşünmeye çalışın. Düğümleri ilgili alana eklemediğiniz veya silmediğiniz sürece bu durum genellikle geçerlidir.

Önce:

function getElements() {
  return $('.my-class');
}

Sonra:

var cachedElements;
function getElements() {
  if (cachedElements) {
    return cachedElements;
  }
  cachedElements = $('.my-class');
  return cachedElements;
}

Önbellek Özellik Değerleri

DOM düğümlerini önbelleğe aldığınız gibi, özellik değerlerini de önbelleğe alabilirsiniz. Bir düğümün stiline ait özelliği canlandırdığınızı düşünün. Bu özelliğe (kodun ilgili bölümünde olduğu gibi) dokunacak tek kişi olduğunuzu biliyorsanız, her yinelemede son değeri önbelleğe alabilirsiniz. Böylece, ilgili kodu tekrar tekrar okumak zorunda kalmazsınız.

Önce:

setInterval(function() {
  var ele = $('#element');
  var left = parseInt(ele.css('left'), 10);
  ele.css('left', (left + 5) + 'px');
}, 1000 / 30);

Sonra: js var ele = $('#element'); var left = parseInt(ele.css('left'), 10); setInterval(function() { left += 5; ele.css('left', left + 'px'); }, 1000 / 30);

DOM Manipülasyonunu Döngülerin Dışarı Taşıma

Döngüler genellikle optimizasyon için kritik noktalardır. Gerçek sayılarda yoğunlaşmayı DOM ile çalışacak şekilde ayrıştırmanın yollarını düşünmeye çalışın. Çoğu zaman bir hesaplama yapıp ardından tüm sonuçları bir kerede uygulayabilirsiniz.

Önce:

document.getElementById('target').innerHTML = '';
for(var i = 0; i < array.length; i++) {
  var val = doSomething(array[i]);
  document.getElementById('target').innerHTML += val;
}

Sonra:

var stringBuilder = [];
for(var i = 0; i < array.length; i++) {
  var val = doSomething(array[i]);
  stringBuilder.push(val);
}
document.getElementById('target').innerHTML = stringBuilder.join('');

Yeniden Çizmeler ve Yeniden Düzenlemeler

Daha önce de belirtildiği gibi, DOM'ye erişim nispeten yavaştır. Kodunuz kısa süre önce DOM ile ilgili bir öğeyi değiştirdiği için yeniden hesaplanması gereken bir değer okurken bu süre çok yavaşlar. Bu nedenle, DOM için okuma ve yazma erişimini karıştırmaktan kaçınılmalıdır. İdeal olarak, kodunuz her zaman iki aşamada gruplandırılmalıdır:

  • 1. Aşama: Kodunuz için gerekli DOM değerlerini okuma
  • 2. Aşama: DOM'da değişiklik yapma

Aşağıdaki gibi bir kalıp programlamamaya çalışın:

  • 1. Aşama: DOM değerlerini okuma
  • 2. Aşama: DOM'da değişiklik yapma
  • 3. Aşama: Daha fazla bilgi edinin
  • 4. Aşama: DOM'u başka bir yerde değiştirin.

Önce:

function paintSlow() {
  var left1 = $('#thing1').css('left');
  $('#otherThing1').css('left', left);
  var left2 = $('#thing2').css('left');
  $('#otherThing2').css('left', left);
}

Sonra:

function paintFast() {
  var left1 = $('#thing1').css('left');
  var left2 = $('#thing2').css('left');
  $('#otherThing1').css('left', left);
  $('#otherThing2').css('left', left);
}

Bu öneri, tek bir JavaScript yürütme bağlamında gerçekleşen işlemler için dikkate alınmalıdır. (ör. bir olay işleyici içinde, bir aralık işleyici içinde veya bir ajax yanıtı işlenirken.)

Yukarıdan paintSlow() işlevi çalıştırıldığında şu görüntü oluşturulur:

paintSlow()

Daha hızlı uygulamaya geçildiğinde aşağıdaki görüntü elde edilir:

Daha hızlı uygulama

Bu resimler, kodunuzun DOM'ye erişme şeklini yeniden sıralamanın oluşturma performansını önemli ölçüde artırabileceğini göstermektedir. Bu durumda, orijinal kodun aynı sonucu oluşturmak için stilleri yeniden hesaplaması ve sayfayı iki kez yerleştirmesi gerekir. Benzer bir optimizasyon, temelde tüm "gerçek dünya" kodlarına uygulanabilir ve gerçekten etkileyici sonuçlar verir.

Devamını okuyun: Oluşturma: yeniden boyama, düzenleme/yeniden düzenleme, yeniden biçimlendirme, Stoyan Stefanov

Yeniden çizimler ve Etkinlik Döngüsü

Tarayıcıda JavaScript yürütme işlemi "Etkinlik Döngüsü" modelini izler. Tarayıcı varsayılan olarak "boşta" durumundadır. Bu durum, kullanıcı etkileşimlerinden kaynaklanan etkinlikler veya JavaScript zamanlayıcıları ya da Ajax geri çağırmaları gibi şeyler nedeniyle kesintiye uğrayabilir. Bir JavaScript parçası böyle bir kesinti noktasında çalıştığında, tarayıcı genellikle ekranı yeniden boyanıncaya kadar işlemin bitmesini bekler (Çok uzun süre çalışan JavaScript'ler veya JavaScript'in çalışmasını etkin bir şekilde kesintiye uğratan uyarı kutuları gibi durumlarda istisnalar olabilir).

Sonuçlar

  1. JavaScript animasyon döngülerinizin yürütülmesi 1/30 saniyeden uzun sürerse tarayıcı, JS yürütme sırasında yeniden boyamayacağı için akıcı animasyonlar oluşturamazsınız. Kullanıcı etkinliklerini de işlemeyi planlıyorsanız çok daha hızlı olmanız gerekir.
  2. Bazen bazı JavaScript işlemlerini biraz sonrasına ertelemek işe yarayabilir. setTimeout(function() { ... }, 0) Bunun, zaman içinde birbirine çok yakın olan iki JavaScript yürütme döngüsü oluşturacağını unutmayın. Her ikisi de ekranın yeniden boyanmasını tetikleyebilir ve bu da boyama için harcanan toplam süreyi iki katına çıkarabilir. Bunun gerçekten iki boyayı tetikleyip tetiklememesi, tarayıcıdaki buluşsal yöntemlere bağlıdır.

Normal sürüm:

function paintFast() {
  var height1 = $('#thing1').css('height');
  var height2 = $('#thing2').css('height');
  $('#otherThing1').css('height', '20px');
  $('#otherThing2').css('height', '20px');
}
Yeniden çizimler ve Etkinlik Döngüsü

Biraz gecikme ekleyelim:

function paintALittleLater() {
  var height1 = $('#thing1').css('height');
  var height2 = $('#thing2').css('height');
  $('#otherThing1').css('height', '20px');
  setTimeout(function() {
    $('#otherThing2').css('height', '20px');
  }, 10)
}
Gecikme

Geciken sürüm, sayfadaki iki değişiklik saniyenin yalnızca 1/100'ü kadar olsa da tarayıcının iki kez boyadığını gösterir.

Geç Başlatma

Kullanıcılar hızlı yüklenen ve duyarlı görünen web uygulamaları ister. Ancak, kullanıcıların yavaş olarak algıladıkları eyleme bağlı olarak farklı eşikleri vardır. Örneğin, bir uygulama fareyle üzerine gelme etkinliğinde hiçbir zaman çok fazla hesaplama yapmamalıdır, çünkü kullanıcı faresini hareket ettirmeye devam ederken kötü bir kullanıcı deneyimine neden olabilir. Ancak kullanıcılar bir düğmeyi tıkladıktan sonra kısa bir gecikmeyi kabul etmeye alışkındır.

Dolayısıyla, başlatma kodunuzu mümkün olduğunca geç yürütülecek şekilde taşımak mantıklı olabilir (ör. kullanıcı, uygulamanızın belirli bir bileşenini etkinleştiren bir düğmeyi tıkladığında).

Şu tarihten önce: js var things = $('.ele > .other * div.className'); $('#button').click(function() { things.show() });

Sonra: js $('#button').click(function() { $('.ele > .other * div.className').show() });

Etkinlik Yetkisi

Etkinlik işleyicilerin bir sayfaya yayılması, nispeten uzun sürebilir ve öğeler dinamik olarak değiştirildikten sonra etkinlik işleyicilerin yeni öğelere yeniden eklenmesini gerektirdiğinde yorucu olabilir.

Bu durumda çözüm, etkinlik yetkisi adı verilen bir teknik kullanmaktır. Öğelere tek tek etkinlik işleyiciler eklemek yerine, etkinlik işleyicinin gerçekten bir üst düğüme eklenmesi ve etkinliğin hedef düğümünü kontrol ederek etkinliğin ilgi çekici olup olmadığı kontrol edilir.

jQuery'de bu, şu şekilde kolayca ifade edilebilir:

$('#parentNode').delegate('.button', 'click', function() { ... });

Etkinlik yetkilendirmesi ne zaman kullanılamaz?

Bazen tam tersi geçerli olabilir: Etkinlik yetkisi kullanıyorsunuz ve performansla ilgili bir sorun yaşıyorsunuz. Olay yetkisi temel olarak sabit karmaşıklıkta başlatma süresine olanak tanır. Ancak, bir etkinliğin ilgi alanı dahilinde olup olmadığını kontrol etme ücreti, bu etkinliğin her çağrılması karşılığında ödenmelidir. Bu, özellikle "mouseover" ve hatta "mousemove" gibi sık gerçekleşen etkinlikler için pahalıya gelebilir.

Tipik Sorunlar ve Çözümler

$(document).ready uygulamasında yaptığım işlemler uzun sürüyor

Malte'nin kişisel tavsiyesi: $(document).ready dilinde asla bir şey yapmayın. Belgenizi son biçiminde teslim etmeye çalışın. Tamam, yalnızca kimlik seçiciyi ve/veya etkinlik yetkisini kullanarak etkinlik işleyicileri kaydedebilirsiniz. "mousemove" gibi pahalı etkinlikler için kaydı, ihtiyaç duyulana kadar erteleyin (ilgili öğede fareyle üzerine gelme etkinliği).

Gerçek verileri almak için Ajax isteğinde bulunmak gibi gerçekten bir şeyler yapmanız gerekiyorsa güzel bir animasyon gösterin; animasyonlu GIF veya benzeri bir animasyon ise veri URI'sı olarak ekleyebilirsiniz.

Sayfaya bir Flash filmi eklediğim için her şey çok yavaş

Pencerenin son düzeninin tarayıcı ile Flash eklentisi arasında "anlaşması" gerektiğinden, sayfaya Flash eklemek oluşturma işlemini her zaman biraz yavaşlatır. Sayfalarınıza Flash yerleştirmekten tamamen kaçınamadığınızda, "wmode" Flash parametresini "window" değerine (varsayılan değer) ayarladığınızdan emin olun. Bu, HTML ve Flash öğelerinin birleştirilmesi özelliğini devre dışı bırakır (Flash filminin üzerinde yer alan bir HTML öğesini göremezsiniz ve Flash filminiz şeffaf olamaz). Bu, rahatsızlık yaratabilir ancak performansınızı önemli ölçüde artırır. Örneğin, youtube.com'un, katmanları ana film oynatıcısının üstüne yerleştirmekten dikkatli bir şekilde kaçınma yöntemlerine göz atın.

Bir şeyleri localStorage'a kaydediyorum, şimdi uygulamam duraklıyor

localStorage'a yazma, sabit diskinizi çalıştırmayı içeren eşzamanlı bir işlemdir. Animasyonlar yaparken hiçbir zaman "uzun süreli" eşzamanlı işlemler yapmak istemezsiniz. localStorage erişimini, kullanıcının boşta olduğundan ve herhangi bir animasyonun devam etmediğinden emin olduğunuz bir noktaya taşıyın.

Profil oluşturma, bir jQuery seçicinin çok yavaş olduğunu gösteriyor

Öncelikle, seçicinizin document.querySelectorAll aracılığıyla çalıştırılabileceğinden emin olmanız gerekir. Bunu JavaScript konsolunda test edebilirsiniz. İstisna olarak seçicinizi JavaScript çerçevenizin herhangi bir özel uzantısını kullanmayacak şekilde yeniden yazın. Bu, modern tarayıcılarda seçicinizi büyüklük sırasına göre hızlandırır.

Bu işe yaramazsa veya modern tarayıcılarda da hızlı olmak istiyorsanız aşağıdaki yönergeleri uygulayın:

  • Seçicinizin sağ tarafında mümkün olduğunca ayrıntılı bilgi verin.
  • En sağdaki seçici bölümü olarak, çok kullanmadığınız bir etiket adı kullanın.
  • Hiçbir şey işe yaramıyorsa kimlik seçici kullanmak için öğeleri yeniden yazmayı düşünün

Tüm bu DOM işleme işlemleri çok uzun zaman alır

Bir dizi DOM düğümü ekleme, kaldırma ve güncelleme işlemleri çok yavaş olabiliyor. Bu, genellikle büyük bir html dizesi oluşturularak ve eski içeriği değiştirmek için domNode.innerHTML = newHTML kullanılarak optimize edilebilir. Bunun bakım açısından çok kötü olabileceğini ve IE'de bellek bağlantıları oluşturabileceğinden dikkatli olun.

Yaygın olarak karşılaşılan bir diğer sorun da başlatma kodunuzun çok fazla HTML oluşturması olabilir. Örneğin, kullanıcı deneyimiyle ilgili en iyi uygulamalardan haberdar olunmayan tasarım kullanıcıların istediği bu olduğundan, bir seçme kutusunu çok sayıda div öğesine dönüştüren bir jQuery eklentisi buna örnek gösterilebilir. Sayfanızın gerçekten hızlı olmasını istiyorsanız bunu asla yapmayın. Bunun yerine, sunucu tarafındaki tüm işaretlemeyi son biçiminde yayınlayın. Burada da pek çok sorun var. Bu yüzden, hızdan ödün vermeye değip değmeyeceğini iyi düşünün.

Araçlar

  1. JSPerf - Küçük JavaScript snippet'lerini karşılaştırın
  2. Firebug - Firefox'ta profil oluşturma için
  3. Google Chrome Geliştirici Araçları (Safari'de Webİnceleyici olarak kullanılabilir)
  4. DOM Monster - DOM performansını optimize etmek için
  5. DynaTrace Ajax Edition - Internet Explorer'da profil oluşturma ve boyama optimizasyonları için

Daha fazla bilgi

  1. Google Hızı
  2. Paul Ireland, jQuery Performance ile ilgili
  3. Olağanüstü JavaScript Performansı (Slayt Grubu)