Daha yüksek hız: Javascript Optimizasyonu

Daha yüksek hız: Javascript Optimizasyonu

Kullanıcılara yönelik kodlamalar ve programlamalar aplikasyonları daha dinamik ve etkili hale getirir fakat tarayıcının bu kodu yorumlaması dolayısıyla ortaya problemler çıkabiliyor.  Farklı farklı yapıların performansı ise kullanıcıdan kullanıcıya değişiyor. Javascript’le çalışmayı bilenler için Javascriptleri optimize edilmesiyle ilgili bazı tavsiyelerimiz olacak.

Satırlar üzerindeki işlemler

Stringlerin arka arkaya eklenmesi(concatenation) yani toplanması İnternet Explorer 6 ve 7’de çöp koleksiyorının performansında çok ciddi problemlere neden oluyor. İnternet Explorer 8 de nihayet bu sorunlar fark edilebildi ve satırların birleştirilmesi birazcık daha IE8de ve IE olmayan tarayıcılarda örneğin Chrome daha isabetli sonuçlar verebiliyor. Eğer kullanıcılarınız Explorer 6 ve 7 kullanıyorsa,  satırlarınızı yapılandırırken çok daha dikkatli olmanız gerekiyor.

Şu örneğe bir göz atalıım:

var veryLongMessage =
‘This is a long string that due to our strict line length limit of’ +
maxCharsPerLine +
‘ characters per line must be wrapped. ‘ +
percentWhoDislike +
‘% of engineers dislike this rule. The line length limit is for ‘ +
‘ style purposes, but we don’t want it to have a performance impact.’ +
‘ So the question is how should we do the wrapping?’;

Ekleme yerine Join kullanın:

var veryLongMessage =
['This is a long string that due to our strict line length limit of',
maxCharsPerLine,
' characters per line must be wrapped. ',
percentWhoDislike,
'% of engineers dislike this rule. The line length limit is for ',
' style purposes, but we don't want it to have a performance impact.',
' So the question is how should we do the wrapping?'
].join();

Aynı şekilde, kondisyonal ifadelerden sonra string yapılandırmak ve/veya eklemeler kullanarak looplar oluşturmak oldukça verimsiz sonuçlara neden olabilir. Yanlış yol:

var fibonacciStr = ‘First 20 Fibonacci Numbers

‘;
for (var i = 0; i < 20; i++) {
fibonacciStr += i + ‘ = ‘ + fibonacci(i) + ‘
‘;
}

Doğru yol:

var strBuilder = ['First 20 fibonacci numbers:'];
for (var i = 0; i < 20; i++) {
  strBuilder.push(i, ‘ = ‘, fibonacci(i));
}
var fibonacciStr = strBuilder.join(”);

Yardımcı fonksiyonlardan gelen parçalarla satır yapılandırılması

Geçici sonuç verecek stringler oluşmasın diye String Builder komudunu kullanarak(ya da array veya helper class) uzun satırları fonksiyona  ekleyin.

Örneğin, diyelim ki  buildMenuItemHtml_  literallerden ve variablelardan bir satır yaratmak istiyoruz, bu durumda stringer builder  içerden kullanılmalıdır. Örneğin şunu yapmayın:

var strBuilder = [];
for (var i = 0, length = menuItems.length; i < length; i++) {
  strBuilder.push(this.buildMenuItemHtml_(menuItems[i]));
}
var menuHtml = strBuilder.join();

 Şunu kullanın:

var strBuilder = [];

for (var i = 0, length = menuItems.length; i < length; i++) {
  this.buildMenuItem_(menuItems[i], strBuilder);
}
var menuHtml = strBuilder.join();

 Class Method belirlenmesi

Aşağıda göreceğiniz tamamen verimsiz bir kullanımdır,  her oluşturulan baz.Bar   için, yeni bir fonksiyon ve closure  oluşturulmuş:

baz.Bar = function() {
  // constructor body
  this.foo = function() {
  // method body
  };
}

Tercih edilmesi gereken yaklaşım ise şöyle:

baz.Bar = function() {
  // constructor body
};

baz.Bar.prototype.foo = function() {
  // method body
};

 Bu yaklaşımla, her ne kadar baz.bar yapılandırılmış olsa dahi, foo için sadece tek bir fonksiyon oluşturulmuş olunuyor ve closure kesinlikle yaratılmıyor.

Anlık Değişken

İnstance variable(Anlık değişken, daha fazla bilgi için: https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html)nin tanımlamasını/değeratamasını değer tip içeren(referans türündense) değer ataması(value initialization) sahibi olan anlık değişkenler için prototype’a yerleştirin. Bu kodun her seferinde ‘constructor’(Constructor, yani “Kurucu” herhangi bir sınıfın nesnesi oluşturulacağı esna o sınıf içerisinde, en başta çalışacak olan kod parçasıdır) tarafından istendiğinde gereksizce yürütülmesini engelleyecektir. (Bu işlem baş değeri(initial value) constructor’daki argumentlere bağlı olan  anlık değişkenlerde kullanılamaz)

Örneğin bunun yerine

foo.Bar = function() {
  this.prop1_ = 4;
  this.prop2_ = true;
  this.prop3_ = [];
  this.prop4_ = ‘blah’;
};

 Bunu kullanın:

 foo.Bar = function() {

  this.prop3_ = [];
};

foo.Bar.prototype.prop1_ = 4;

foo.Bar.prototype.prop2_ = true;

foo.Bar.prototype.prop4_ = ‘blah’;

Closure

Closurelar Javascript’in  oldukça güçlü ve işe yarar bir uygulaması, fakat,birkaç bunun yanında yarattığı birkaç olumsuz durum da var. Onlardan biri de:

-Bellek sızıntılarının ana kaynaklarından birini bunlar oluşturuyor.
-Bir closure yaratmak closure içermeyen bir iç fonksiyon yaratmaktan çok daha yavaş, hatta  bir statik fonksiyonu kullanmaktan çok daha yavaş. Örneğin:

function setupAlertTimeout() {
  var msg = ‘Message to alert’;
  window.setTimeout(function() { alert(msg); }, 100);
}

 Bundan daha yavaş:

function setupAlertTimeout() {

  window.setTimeout(function() {
    var msg = ‘Message to alert’;
    alert(msg);
  }, 100);
}

 O da bundan daha yavaş:

function alertMsg() {

  var msg = ‘Message to alert’;
  alert(msg);
}

function setupAlertTimeout() {
  window.setTimeout(alertMsg, 100);
}

 Bunların hepsi scope zincirine bir kademe daha ekler. Tarayıcı özellikleri çözümlerken scope zincirinin her kademesini kontrol etmek zorundadır. Örnekte de görüldüğü gibi:

var a = ‘a’;

function createFunctionWithClosure() {
  var b = ‘b’;
  return function () {
    var c = ‘c’;
    a;
    b;
    c;
  };
}

var f = createFunctionWithClosure();
f();

F çağrıldığında, a’nın referanslanması b’nin referanslanmasından daha yavaştır, b’nin referanslanması da c’nin referanslanmasından daha yavaştır.

With’den kaçının

Kodlamada with kullanmaktan kaçının. Performansa gerçekten çok negativ bir etkisi var scope örgüsünü modifiye etmesiyle beraber, başka scopelardaki değişkenlerle ilgili verileri araştırmak çok daha zorlu hale geliyor.

Tarayıcılardaki Bellek sızıntılarının önüne geçme

Bellek sızıntısı, web aplikasyonlarında çok sık görülen ve performansa çok büyük zararlar veren bir problem. Tarayıcının kullandığı bellek miktarı arttıkça , web aplikasyonunuz, kullanıcınn sisteminin geri kalanıyla beraber büyük yavaşlamaya maruz kalıyor. Web aplikasyonları için en çok görülen hafıza sızıntısı Javascript’in script motoru ile tarayıcının DOM içeren C++ objeleri arasındaki ‘circular reference’(programlama dillerinde iki ayrı modülün birbirlerine bağımlı olması halinde ortaya çıkan bir hatadır.)lerde ortaya çıkıyor. (Javascript script motoru ve Internet Explorer’ın COM altyapısı ile, Javascript motoru ile BU konuda yardımcı olacak tavsiyeler ve kuralları aşağıda bulabilirsiniz:

Circular Reference hatasının en çok görülen hata kalıbı şöyle: DOM objesi ->  event handler -> closure scope -> DOM. Bu konuda a internette birçok işe yarar bilgi mevcut. Bu problemin önüne geçebilmek için, derinlemesine test edilmiş event systemlerini kullanmak gerekiyor, örneğin Google doctype, Dojo ya da Jquery gibi.



Yorum Yazın

Profesyonel destek için iletişime geçin. İletişim