Kullanıcı zamanlama API'si

Web uygulamanızı anlama

Alex Danilo

Yüksek performanslı web uygulamaları, mükemmel bir kullanıcı deneyimi için çok önemlidir. Web uygulamaları giderek daha karmaşık hale geldikçe performans etkisini anlamak, ilgi çekici bir deneyim oluşturmak için hayati önem taşır. Son birkaç yılda, ağın performansını, yükleme sürelerini vb. analiz etmeye yardımcı olmak için tarayıcıda bir dizi farklı API kullanıma sunuldu. Ancak bunlar, uygulamanızı yavaşlatan unsurları bulmak için yeterli esneklikle ayrıntılı bilgi sağlamaz. Web uygulamanızın zamanını nerede harcadığını belirlemek için uygulamanızı ölçmek amacıyla kullanabileceğiniz bir mekanizma sağlayan User Timing API'yi girin. Bu makalede, API'yi ve kullanım örneklerini ele alacağız.

Ölçemediğiniz şeyi optimize edemezsiniz

Yavaş bir web uygulamasını hızlandırmanın ilk adımı, zamanın nerede harcandığını bulmaktır. JavaScript kodu alanlarının zaman etkisini ölçmek, performansın nasıl iyileştirileceğini bulmanın ilk adımı olan etkin noktaları belirlemenin ideal yoludur. Neyse ki User Timing API, JavaScript'inizin farklı bölümlerine API çağrıları eklemenize ve ardından optimizasyon için kullanılabilecek ayrıntılı kullanıcı zamanlamaları verilerini ayıklamanıza olanak tanır.

Yüksek çözünürlük süresi ve now()

Doğru zaman ölçümünün temel bir parçası hassasiyettir. Eskiden milisaniye ölçümüne dayalı zamanlamamız vardı. Bu iyi bir yöntemdi ancak 60 FPS'lik takılmasız bir site oluşturmak için her karenin 16 milisaniyede çizilmesi gerekir. Bu nedenle, yalnızca milisaniye doğruluğuna sahip olduğunuzda iyi bir analiz için gereken hassasiyetten yoksun olursunuz. Modern tarayıcılarda yerleşik olarak bulunan yeni bir zamanlama türü olan Yüksek Çözünürlüklü Zaman'ı kullanın. Yüksek Çözünürlüklü Zaman, bize mikrosaniye çözünürlüğe kadar doğru olabilen kayan nokta zaman damgaları sağlar. Bu, eskisinden bin kat daha iyidir.

Web uygulamanızda geçerli saati öğrenmek için Performance arayüzünün uzantısını oluşturan now() yöntemini çağırın. Aşağıdaki kodda bunun nasıl yapılacağı gösterilmektedir:

var myTime = window.performance.now();

Web uygulamanızın nasıl yüklendiğiyle ilgili farklı süreler sağlayan PerformanceTiming adlı başka bir arayüz daha vardır. now() yöntemi, navigationStartPerformanceTiming'deki zamanın gerçekleştiği andan itibaren geçen süreyi döndürür.

DOMHighResTimeStamp türü

Geçmişte web uygulamalarını zamanlamaya çalışırken DOMTimeStamp döndüren Date.now() gibi bir yöntem kullanırdınız. DOMTimeStamp, değer olarak milisaniye cinsinden bir tam sayı döndürür. Yüksek çözünürlüklü zaman için gereken daha yüksek doğruluğu sağlamak amacıyla DOMHighResTimeStamp adlı yeni bir tür kullanıma sunuldu. Bu tür, zamanı milisaniye cinsinden de döndüren bir kayan nokta değeridir. Ancak kayan nokta olduğu için değer, milisaniyenin kesirlerini temsil edebilir ve bu nedenle milisaniyenin binde biri kadar doğruluk sağlayabilir.

Kullanıcı Zamanlaması arayüzü

Artık yüksek çözünürlüklü zaman damgalarımız olduğuna göre, zamanlama bilgilerini almak için Kullanıcı Zamanlamaları arayüzünü kullanalım.

Kullanıcı Zamanlaması arayüzü, uygulamamızın farklı yerlerinde yöntemleri çağırmamıza olanak tanıyan işlevler sağlar. Bu işlevler, Hansel ve Gretel tarzı bir içerik haritası izi sağlayarak zamanın nerede harcandığını izlememize olanak tanır.

mark() kullanılıyor

mark() yöntemi, zamanlama analizi araç setimizdeki ana araçtır. mark(), bizim için bir zaman damgası depolar. mark() ile ilgili en faydalı şey, zaman damgasını adlandırabilmemiz ve API'nin adı ve zaman damgasını tek bir birim olarak hatırlamasıdır.

Uygulamanızın çeşitli yerlerinde mark() yöntemini çağırmak, web uygulamanızda bu "işarete" ulaşmanızın ne kadar sürdüğünü hesaplamanıza olanak tanır.

Spesifikasyon, ilgi çekici olabilecek ve oldukça açıklayıcı olan işaretler için mark_fully_loaded, mark_fully_visible, mark_above_the_fold gibi önerilen adları belirtir.

Örneğin, aşağıdaki kodu kullanarak uygulamanın tamamen yüklendiği an için bir işaret ayarlayabiliriz:

window.performance.mark('mark_fully_loaded');

Web uygulamamızda adlandırılmış işaretler ayarlayarak çok sayıda zamanlama verisi toplayabilir ve uygulamanın neyi ne zaman yaptığını anlamak için bu verileri istediğimiz zaman analiz edebiliriz.

measure() ile ölçümler hesaplanıyor

Birkaç zamanlama işareti ayarladıktan sonra, aralarında geçen süreyi öğrenmek isteyebilirsiniz. Bunun için measure() yöntemini kullanırsınız.

measure() yöntemi, işaretler arasında geçen süreyi hesaplar ve işaretiniz ile PerformanceTiming arayüzündeki iyi bilinen etkinlik adlarından herhangi biri arasındaki süreyi de ölçebilir.

Örneğin, DOM'un tamamlanmasından uygulama durumunuzun tamamen yüklenmesine kadar geçen süreyi aşağıdaki gibi bir kod kullanarak hesaplayabilirsiniz:

window.performance.measure('measure_load_from_dom', 'domComplete', 'mark_fully_loaded');

measure() yöntemini çağırdığınızda, sonucu ayarladığınız işaretlerden bağımsız olarak depolar. Böylece daha sonra bu işaretleri alabilirsiniz. Uygulamanız çalışırken zamanları depolayarak uygulamanın yanıt vermeye devam etmesini sağlayabilir ve uygulamanız bazı işlemleri tamamladıktan sonra tüm verileri daha sonra analiz edilmek üzere dökebilirsiniz.

clearMarks() ile işaretler siliniyor

Bazen, ayarladığınız bir grup işareti kaldırabilmek faydalı olabilir. Örneğin, web uygulamanızda toplu çalıştırmalar yapıyorsanız her çalıştırmaya sıfırdan başlamak isteyebilirsiniz.

clearMarks() yöntemini çağırarak ayarladığınız tüm işaretleri kolayca kaldırabilirsiniz.

Aşağıdaki örnek kod, mevcut tüm işaretlerinizi siler. Böylece isterseniz zamanlama çalıştırmasını tekrar ayarlayabilirsiniz.

window.performance.clearMarks();

Elbette, tüm işaretlerinizi temizlemek istemeyeceğiniz bazı senaryolar vardır. Belirli işaretleri kaldırmak istiyorsanız kaldırmak istediğiniz işaretin adını iletebilirsiniz. Örneğin, aşağıdaki kod:

window.performance.clearMarks('mark_fully_loaded');

ilk örnekte ayarladığımız işareti kaldırır, ayarladığımız diğer işaretleri ise değiştirmez.

Yaptığınız ölçümleri de kaldırmak isteyebilirsiniz. Bunun için clearMeasures() adlı bir yöntem vardır. clearMarks() ile tamamen aynı şekilde çalışır ancak yaptığınız tüm ölçümlerde çalışır. Örneğin, şu kod:

window.performance.clearMeasures('measure_load_from_dom');

Yukarıdaki measure() örneğinde oluşturduğumuz ölçüyü kaldırır. Tüm ölçümleri kaldırmak istiyorsanız clearMarks() ile aynı şekilde çalışır. clearMeasures() işlevini bağımsız değişkenler olmadan çağırmanız yeterlidir.

Zamanlama verilerini alma

İşaretleri ayarlamak ve aralıkları ölçmek iyi ve güzeldir ancak bir noktada analiz yapmak için bu zamanlama verilerine ulaşmak istersiniz. Bu da çok basit. Tek yapmanız gereken PerformanceTimeline arayüzünü kullanmak.

Örneğin, getEntriesByType() yöntemi, tüm işaretleme sürelerimizi veya tüm ölçüm sürelerimizi liste halinde almamızı sağlar. Böylece bu süreleri tekrarlayabilir ve verileri sindirebiliriz. Listenin kronolojik sırayla döndürülmesi, işaretleri web uygulamanızda ulaşıldıkları sırayla görmenizi sağlar.

Aşağıdaki kod:

var items = window.performance.getEntriesByType('mark');

web uygulamamızda ulaşılan tüm işaretlerin listesini döndürür. Aşağıdaki kod ise:

var items = window.performance.getEntriesByType('measure');

yaptığımız tüm ölçümlerin listesini döndürür.

Girişlere verdiğiniz özel adı kullanarak da girişlerin listesini alabilirsiniz. Örneğin, aşağıdaki kod:

var items = window.performance.getEntriesByName('mark_fully_loaded');

startTime özelliğinde "mark_fully_loaded" zaman damgasını içeren tek öğeli bir liste döndürür.

XHR isteğini zamanlama (örnek)

User Timing API hakkında yeterli bilgiye sahip olduğumuza göre, web uygulamamızdaki tüm XMLHttpRequests'lerin ne kadar sürdüğünü analiz etmek için bu API'yi kullanabiliriz.

Öncelikle tüm send() isteklerimizi, işaretleri ayarlayan bir işlev çağrısı yapacak şekilde değiştireceğiz. Aynı zamanda, başarı geri çağırmalarımızı başka bir işaret ayarlayan ve ardından isteğin ne kadar sürdüğünü ölçen bir işlev çağrısıyla değiştireceğiz.

Normalde XMLHttpRequest'imiz şuna benzer:

var myReq = new XMLHttpRequest();
myReq.open('GET', url, true);
myReq.onload = function(e) {
  do_something(e.responseText);
}
myReq.send();

Örneğimizde, istek sayısını izlemek ve her isteğin ölçümünü depolamak için genel bir sayaç ekleyeceğiz. Bunu yapmak için gereken kod şu şekildedir:

var reqCnt = 0;

var myReq = new XMLHttpRequest();
myReq.open('GET', url, true);
myReq.onload = function(e) {
  window.performance.mark('mark_end_xhr');
  reqCnt++;
  window.performance.measure('measure_xhr_' + reqCnt, 'mark_start_xhr', 'mark_end_xhr');
  do_something(e.responseText);
}
window.performance.mark('mark_start_xhr');
myReq.send();

Yukarıdaki kod, gönderdiğimiz her XMLHttpRequest için benzersiz bir ad değerine sahip bir ölçüm oluşturur. İsteklerin sırayla çalıştığını varsayıyoruz. Paralel isteklerin kodu, sırasız olarak dönen istekleri işlemek için biraz daha karmaşık olmalıdır. Bunu okuyucuya bir alıştırma olarak bırakıyoruz.

Web uygulaması bir dizi istek yaptıktan sonra aşağıdaki kodu kullanarak hepsini konsola dökebiliriz:

var items = window.performance.getEntriesByType('measure');
for (var i = 0; i < items.length; ++i) {
  var req = items[i];
  console.log('XHR ' + req.name + ' took ' + req.duration + 'ms');
}

Sonuç

User Timing API, web uygulamanızın her yönüne uygulayabileceğiniz birçok harika araç sunar. Uygulamanızdaki yoğun noktaları daraltmak, web uygulamanızın her yerine API çağrıları ekleyerek ve zamanın nerede harcandığına dair net bir resim oluşturmak için oluşturulan zamanlama verilerini sonradan işleyerek kolayca yapılabilir. Peki ya tarayıcınız bu API'yi desteklemiyorsa? Sorun değil, API'yi çok iyi taklit eden ve webpagetest.org ile de iyi çalışan mükemmel bir polyfill'i burada bulabilirsiniz. Daha ne bekliyorsunuz? Uygulamalarınızda Kullanıcı Zamanlamaları API'sini hemen deneyin. Uygulamalarınızı nasıl hızlandıracağınızı öğreneceksiniz ve kullanıcılarınız deneyimlerini çok daha iyi hale getirdiğiniz için size teşekkür edecek.