Javascript ile performanslı kod nasıl yazılır ?

Tayfun YUGRUK
Kod42 Akademi
Published in
4 min readJul 12, 2020

Bir önceki yazılarımda Javascript çalışma ortamını derinlemesine incelemiştik eğer okumadıysanız aşağıdaki linklerden erişerek okuyabilirsiniz.

Ayrıca videolu anlatımlar ile daha kolay anlıyorsanız bu yazı dizisinin videolarına aşağıdaki linkten erişebilirsiniz :

Bu yazı ile günümüzde en çok kullanılan Javascript motoru olan V8 için daha performanslı nasıl kod yazmalıyız detaylı şekilde anlatacağım. Bu yazıdaki öneriler sadece V8 motoru için değil diğer Javascript motorları için de kullanılabilir.

V8 Javascript motoru kodları çalıştırırken 2 ana parçadan oluşur.

  • Ignite ( Javascript interpreter )
  • TurboFan ( Javascript JIT Compiler )

Ignite

Ignite interpreter şeklinde kodlarımızdan üretilen bytecode’ları çalıştıran kısımdır.

Javascript kodlarından öncelikle Abstract Syntax Tree oluşturur ve sonrasında bytecode’lar oluşturur. Son olarak bytecode’ları interpreter şeklinde çalışmaktadır.

Bytecode’ları oluştururken sık kullanılan fonksiyonları uygun yerlerde çağrılan fonksiyonun kodunu çağrıldığı yere kopyalayarak performans optimizasyonu uygular fakat bu çok etkili bir optimizasyon değildir.

TurboFan

Kodlardan oluşan bytecode’lar Ignite ile çalıştırılırken TurboFan arka planda çalıştırılan fonksiyonların istatistiğini alır ve sık kullanılan ve native koda dönüştürülebilecek fonksiyonları derleyip native olarak çalışmasını sağlar böylece büyük bir performans artışı sağlar.

TurboFan için önemli nokta etkisini göstermesi için belirli bir süre çalışması gereklidir yani çok kısa çalışan uygulamalar için faydasını göremeyiz.

Nasıl optimize edilebilir Javascript kodu yazmalıyız ?

Javascript kodlarını daha optimize yazmak için amacımız TurboFan’ın çalışması sonucunda ortaya çıkacak native kodları en optimize şekilde ortaya çıkarmasını sağlamaya yardımcı olmaktır. Bunun için şunları yapabiliriz :

Öneri 1: Bir sınıfa ait değişkenleri constructor içinde tanıtmalıyız

TurboFan bir class içindeki değişkenleri index yardımı ile daha hızlı erişmek için Hidden Class dediğimiz data yapılarından faydalanır. Hidden class’lar temel olarak bir sınıfa ait değişkenlerin index’ini tutar dolayısı ile aynı sınıftan yaratılmış instance’lar aynı Hidden class’ı paylaşırlar ve Javascript o sınıfa ait instance’ların değişkenlerine daha hızlı erişir.

Eğer bir sınıftan yaratılmış olan instance’lardan herhangi birine yeni bir değişken eklerseniz bu instance Hidden class desteğini kaybeder ve hashmap tabanlı bir değişken bulma yapısı oluşur ( yani Javascript nesnelerinin varsayılan değişken bulma yöntemi ). Bu da performansı düşürür.

Javascript normalde class veya obje içerisindeki değişkenlere hashmap yöntemi ile erişir yani tek tek içerisindeki değişkenleri isimleri ile kontrol eder ve erişmek istediğimiz değişken bulunduğu zaman ne yapmak istiyorsak gerçekleştirir. Dolayısı ile bir değişkene erişmek zaman alan bir süreçtir. Değişkenler index’lendiği zaman yerleri Hidden class içinde saklanır ve böylece Javascript değişkene daha hızlı erişir çünkü hashmap mantığında olduğu gibi teker teker bakmaz direkt olduğu index üzerinden erişir.

Tahmin edeceğiniz üzere bu noktada performansı ne kadar arttırabilirsek Javascript uygulamamız o kadar hızlı çalışır.

Öneri 2: Sınıf değişkeni sırasını mümkün olduğunda aynı sırada tutun

Hidden class’lar bir instance içindeki değişkenlere erişimi hızlandırır demiştik Öneri 1 içinde, yani amacımız bir Sınıf veya Obje için mümkün olduğunda paylaşılan hidden class’lar oluşturulmasını sağlamak.

Eğer aynı data yapısına sahip iki sınıf veya obje’nin değişken tanım sıraları farklı ise bu sınıf veya objeler için oluşturulan Hidden class’lar da farklı olur !

Yukarıdaki kod bloğunda aslında a1 ve a2 objeleri aynı data yapısına sahip olmasına rağmen değişken tanımlama sırası farklı olduğu için farklı Hidden class’lar oluştu ve TurboFan’ın uygulayabileceği performans optimizasyonu uygulanamaz hale geldi.

Bu sebeple sınıf veya objeleriniz içinde mümkün olduğunca değişkenleri aynı sırada oluşturun ve hatta mümkün olduğunda sonradan değişken eklemeyin.

Öneri 3: Fonksiyon parametrelerini sabit veri tipleri alacak şekilde ayarlayın

Eğer çağrılan bir Javascript fonksiyonu uygulama içinde farklı yerlerde farklı parametre tipleri ile çağrılıyor ise bu fonksiyon için optimizasyon uygulanmaz.

Yukarıdaki örnekte gördüğünüz üzere aynı fonksiyon farklı parametre tipleri ile çağrılıyor dolayısı ile V8 bu fonksiyon için optimizasyon uygulanmayacağına karar verir ve olası bir performans optimizasyonu engellenmiş olur.

Öneri 4: Sınıfları kod scope’u içinde tanımlayın

Sınıfları mümkün olduğunda fonksiyonlar içinde tanımlayıp sonra instance oluşturup döndürme şeklindeki pratikleri uygulamamalıyız.

Yukarıdaki kod örneğinde gördüğünüz gibi Nokta sınıfı hem fonksiyon içinde tanımlanmış hem de bu sınıftan bir instance yaratılıp döndürülmüş. Bu V8 motorunun optimizasyon uygulamasına sebep olan durumlardan biridir.

Bu sebepler sınıf tanımlarını her zaman normal kod akışı içinde tanımlayın yani fonksiyonları tanıttığımız kod bölgesinde tanıtmaları yapın.

Öneri 5 : mümkün olduğunca for…in döngüsü kullanın

V8 dökümanlarına göre forEach döngüsüne göre for…in döngüsünü daha hızlı çalıştırmaktadır bu nedenler mümkün olduğunda kodlarınızdaki döngüleri for…in ile kurgulayın.

--

--