Upload
irfandurmus
View
1.432
Download
4
Embed Size (px)
Citation preview
Web'in öksüz evladı: JavaScript
JavaScript Web tarihi boyunca çok az insanın önemsediği, çok güçlü, prototype tabanlı, Object-Orient bir dildir.
Sunumun amacı:
JavaScript Performans Optimizasyonu
İrfan Durmuş
Web'in öksüz evladı: JavaScript
JavaScript Tarihi: Kısaca..
Geleceğin Teknolojisi: Nerelerde JS kullanılıyor?
Nonblocking pattern: Optimizasyon da ilk adım
Global variables suck!: Global yerine local daha iyi bir seçim
DOM'a erişimin maaliyeti: Git gel Gecko 6 saat
Event binding: Tek binding ile toplu event handle etmek varken..
Döngü içindeki değişkenler: Aynı değeri defalarca istemek gereksiz
Web'in öksüz evladı: JavaScript
JavaScript TarihiKısaca..
JavaScript Tarihi
JS, şu anki Mozilla Vakfı CTO'su Brendan Eich tarafından Netscape için geliştirilmiştir.
İlk kez 1995'de Netscape ile dağıtıldı.
Mocha -> LiveScript -> JavaScript
1996 Kasım'da standartlaştırma için Ecma International'a gönderildi.
Web'in öksüz evladı: JavaScript
Geleceğin TeknolojisiJavaScript Nerelerde Kullanılıyor?
JavaScript: Geleceğin Teknolojisi
250 Milyon web sitesi
PDF Dosyaları
SSB: Site Specific Browsers
Gmail, Twitter, Facebook masaüstü uygulamaları.
Mobil Uygulamalar, Masaüstü Widget'lar
PhoneGap, JSCocoa, Apple Widgets, Microsoft Gadgets
Tarayıcı eklentileri, Masaüstü uygulamaları
Opera, Chrome Eklentileri, Firebug, Chrome Webstore
JavaScript: Geleceğin Teknolojisi
Sunucu tarafında;
Nodejs/V8, mod_js/SpiderMonkey
Onlarca CommonJS implementasyonu çözümü
CommonJS ile;
Sunucu tarafında JavaScript Uygulamaları (CouchDB)
Komut satırı uygulamaları (NodeJS)
Desktop/GUI Uygulamaları (Widget'lar)
Hibrid uygulamalar (Adobe Air)
Başlamadan önce...
Daha iyi anlamak için bilinmesi gerekenler;
JavaScript bir değişkenin içerisinde method taşıyabilir, yani integer, string gibi function type'ımız vardır.
Herşey birer object'dir, yeni bir object için 'class' yerine 'function' kullanırız.
Anonymous function, isimsiz bir scope'dur. Aşağıdaki şekilde yazılır ve parametre gönderilir. Tabii ki bu da objectdir.
(function($, window){
// code...
}(jQuery, wndow));
Prototype tabanlı bir dildir, her objenin bir prototype'ı vardır. Prototype'daki bir değişkene erişirken, 'prototype'sız kullanılır. Aşağıdaki örneği inceleyelim;
function Users(){};
Users.prototype.getUser = function(id){ return id;};
var id = 1,
user = new Users();
user.getUser(id);
Web'in öksüz evladı: JavaScript
Nonblocking PatternOptimizasyonda İlk Adım
Nonblocking Pattern
Nonblocking nedir ve neyi amaçlar?
Tarayıcı script tagını gördüğünde, diğer tüm içeriğin yüklenmesini durdurur (image'ler, css'ler vb.) ve scriptleri yüklemeye başlar.
Script dosyaları yüklendikten sonra derlenme süreci vardır.
Derlenme sürecinde bir sonraki script dosyası da diğer tüm içerik gibi bekletilir.
Inline JavaScript satırları da yorumlanması için JS Engin'e gönderildiğinde diğer tüm içerik bekletilir.
Nonblocking pattern, diğer içeriği engellemeden JavaScript çalıştırmayı amaçlar.
Nonblocking Pattern
Script elementlerinin olduğu bir sayfanın yüklenişi..
0 200 400 600 800 1000 1200 1400 1600 1800 2000
milisaniye
main.js
shared.js
users.js
other.js
style.css
Yükleme süresi Çalıştırma süresi
Nonblocking Pattern
Script tag'leri nerede konumlanmalıdır?
…..
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
</head>
<body>
…..
…..
<script src="js/main.js"></script>
</body>
</html>
Nonblocking Pattern
Nonblocking Teknikleri;
Gecikmeli Scriptler (Deferred Scripts)HTML 4, eski bir teknik ve çoğu taraycı desteklemediği için bahsetmeyeceğiz.
Dinamik Script Elementivar script = document.createElement('script'); script.src=”bar.js”;
document.getElementsByTagName('head')[0].appendChild(script);
AJAX ile Script InjectionXMLHttpRequest aracılığıyla js dosyası alınır ve body e append edilir.
var x = new XMLHttpRequest();
x.open('get', 'main.js', true);
x.onreadystatechange = function(){
//.. xhr kontrol ve append kodları burada..
};
Nonblocking Pattern
Önerilen TeknikTüm dosyaları birleştirin.loader.js ve main.js
Minimizer ve Obfuscator kullanın.Google closure veya YUI
Script taglarını </body> den hemen önce yerleştirin. var script = document.createElement('script'); script.src=”bar.js”;
document.getElementsByTagName('head')[0].appendChild(script);
Sayfadaki tüm argumanların tamamlanmasını bekleyin.Jquery'deki document.ready nin sırrı..
Script tag'ini dinamik oluşturun.loader.js nin görevi: document.createElement('script');
Nonblocking Pattern
Loader çözümleriLazyLoad librarygithub.com/rgrove/lazyload
YUI (Yahoo User Interfaces)http://developer.yahoo.com/yui/
Kendi yazacağınız, 20 satır civarında bir loader. Script tag'i event leri ile script dosyasının yüklenip hazır olduğunu anlayabiliyoruz. Hiç bir
script dosyası sayfa tamamen hazır olmadan yüklenmemeli ve çalıştırılmamalı. obj.readyState (ie) ve/ya obj.onLoad (diğerleri) eventleri beklenmeli. Bu loader, dinamik olarak oluşturacağı script objesine src olarak yüklemek istediğiniz dosya yolunu verdikten sonra sayfaya append etmeli.
Web'in öksüz evladı: JavaScript
Global Variables Suck!Global yerine local çok daha iyi bir seçim.
Global Variables Suck
İçiçe property'leri olan globaldeki bir objenin propertylerine erişmek;
var obj = {};
obj.smth = {};
obj.smth.more = {};
obj.smth.more.first = 2;
obj.smth.more.second = 3;
obj.smth.more.data;
function sum_nested_vars(){
for(var i = 0; i < 200000; i++){
obj.smth.more.data = obj.smth.more.first + obj.smth.more.second;
}
return obj.smth.more.data;
}
sum_nested_vars();
Global Variables Suck
Global değişkenlere/methodlara erişmek
var first = 2,
second = 3;
function sum_global_vars(){
var data;
for(var i = 0; i < 200000; i++){
data = first + second;
}
return data;
}
sum_global_vars();
Global Variables Suck
Local değişkenler kullanmak
function sum_local_vars(){
var first = 2,
second = 3,
data;
for(var i = 0; i < 200000; i++){
data = first + second;
}
return data;
}
sum_local_vars();
Global Variables Suck
GLOBAL AS NESTED
430 milisaniye
GLOBAL DEĞİŞKEN
300 milisaniye
LOCAL DEĞİŞKEN
1 milisaniye
Local Değişken
Global Değişken
Global Obje
0 50 100 150 200 250 300 350 400 450 500
Milisaniye
Global Variables Suck
// …
function sum_nested_vars(){
var first = obj.smth.more.first,
second = obj.smth.more.second,
data = obj.smth.more.data;
for(var i = 0; i < 200000; i++){
data = first + second;
}
obj.smth.more.data = data;
return data;
}
// ...
// ...
function sum_nested_vars(){
for(var i = 0; i < 200000; i++){
obj.smth.more.data = obj.smth.more.first + obj.smth.more.second;
}
return obj.smth.more.data;
}
// ...
Nested global objeden local değişkene optimizasyon. Uygulamanın büyüklüğüne göre bu farkın çok açılacağını veya kapanacağını unutmayın!
430 milisaniye 1 milisaniye
Web'in öksüz evladı: JavaScript
DOM'a Erişimin MaaliyetiGit gel Gecko altı saat.
DOM'a Erişimin Maliyeti
function innerHtmlBadWay(){
for (var i = 0; i < 10000; i++){
document.getElementById('myDiv').innerHTML += 'x';
}
}
innerHtmlBadWay();
Her bir işlem için layout engine'e erişmektense, tüm datayı bir variable içerisinde toplayıp tek seferde yazmak çok daha hızlıdır.
function innerHtmlGoodWay(){
var data = 'x';
for (var i = 0; i < 10000; i++){
data += 'x';
}
document.getElementById('myDiv').innerHTML += data;
}
innerHtmlGoodWay();
X
√
DOM'a Erişimin Maliyeti
Değişkene atamak
Döngü içinde erişmek
0 500 1000 1500 2000 2500 3000 3500
Milisaniye
10.000 kez DOM'a innerHTML ile erişmek yerine datayı değişkene atayıp bir kez layout engine gitmek arasındaki farkı gösteren grafik.
For içinde erişmek: 3050 milisaniye
Variable'a atamak: 1 milisaniye
DOM'a Erişimin Maliyeti
JS Engine( V8 / SpiderMonkey )
Layout Engine( WebKit / Gecko )
Requestdocument.getElementByID('mydiv');
Response<div id='mydiv'></div>
6 saat'lik mesafe
NEDEN?
Web'in öksüz evladı: JavaScript
Event BindingTek binding ile toplu event handle etmek varken..
Event Binding
Event'ler, click, hover, focus, keypress, mouseover vb. DOM eventleri olabileceği gibi, developer tarafından tanımlanmış özel eventler da olabilir.
Event nedir?
Event Binding
document.addEventListener('click', function(){
// code...
});
veya
function foo(){
// code...
};
document.addEventListener('click', foo);
Event listener
Event Binding
Bir event'in işleyişi
<div id=”container”>
<ul id=”navigation”>
<a href=”/main”>Home</a>
<li>
event
Event Binding
Bir event'in işleyişi
Event, window objesine kadar parent'ler üzerinden ilerler.
<div id=”container”>
<ul id=”navigation”>
<a href=”/main”>Home</a>
<li>
event
event
Event objedir ve target property'si vardır. Target property'si tıklanan DOM elementinin referansıdır, ve değişmez.
Event Binding
<ul id=”navigation”>
<li><a href=”/main”>Home</a></li>
<li><a href=”/foo”>Foo</a></li>
<li><a href=”/bar”>Bar</a></li>
<li><a href=”/baz”>Baz</a></li>
<li><a href=”/about”>About</a></li>
</ul>
Event objesi parent'ler üzerinden ilerlediğine göre, her bir link için ayrı ayrı event atamak yerine, liste içerisindeki tüm eventleri burada yakalayabiliriz.
event
Event Binding
(function() {
document.getElementById('navigation').onclick = function(event){
var target = event.target;
if (event.target.tagName == 'A') {
alert('Şu sayfa açılacak: \n\n' + target.attributes[0].value);
document.location = target.attributes[0].value;
};
event.preventDefault();
event.stopPropagation();
}
}());
Web'in öksüz evladı: JavaScript
Döngü İçindeki DeğişkenlerAynı değeri defalarca istemek gereksiz
Döngü İçindeki Değişkenler
for (var i=0; i < things.length; i++) {
typeof things[i];
};
var l = things.length;
for (var i=0; i < l; i++) {
typeof things[i];
};
iyi
daha iyivar l = things.length
i=0;
for (; i < l; i++) {
typeof things[i];
};
kötü
Döngü İçindeki Değişkenler
'for' dışında tanımlamak
'for' içinde length kullanmak
0 5 10 15 20 25 30 35 40 45 50
Milisaniye
55.000 elemanı olan bir array için grafikteki performans farkı gözlenmiştir.
Okunabilecek Kitaplar
Ek:
Kaynaklar:
- Wikipedia
- Nicholas C. Zakas: High Performance JavaScript
İndirilebilir sunum:
slideshare.net/irfandurmus/javascript-performance-optimisation
Sunumdaki Kodlar:
github.com/irfan/javascript-presentation-codes
Web'in öksüz evladı: JavaScript
SORULAR
İrfan Durmuş