AirSHIFT'ın React uygulamasının çalışma zamanı performansını iyileştirmesinin beş yolu

React SPA performans optimizasyonuyla ilgili gerçek dünyadan bir örnek olay.

Kento Tsuji
Kento Tsuji
Satoshi Arai
Satoshi Arai
Yusuke Utsunomiya
Yusuke Utsunomiya
Yosuke Furukawa
Yosuke Furukawa

Web sitesi performansı yalnızca yükleme süresiyle ilgili değildir. Kullanıcılara hızlı ve duyarlı bir deneyim sunmak, özellikle de kullanıcıların her gün kullandığı üretkenlik masaüstü uygulamaları için çok önemlidir. Recruit Technologies'deki mühendislik ekibi, web uygulamalarından biri olan AirSHIFT'ı daha iyi kullanıcı giriş performansı için iyileştirmek üzere yeniden düzenleme projesi gerçekleştirdi. Nasıl yaptıklarına bakalım.

Yavaş yanıt, daha az üretkenlik

AirSHIFT, restoran ve kafe gibi mağaza sahiplerinin, çalışanlarının vardiya işlerini yönetmesine yardımcı olan bir masaüstü web uygulamasıdır. React ile oluşturulan tek sayfalık uygulama, gün, hafta, ay ve diğer koşullara göre düzenlenen vardiya programlarının çeşitli tablo tabloları dahil, zengin istemci özellikleri sağlar.

AirSHIFT web uygulamasının ekran görüntüsü.

Recruit Technologies mühendislik ekibi, AirSHIFT uygulamasına yeni özellikler ekledikçe düşük performansla ilgili daha fazla geri bildirim görmeye başladılar. AirSHIFT mühendislik müdürü Yosuke Furukawa şöyle diyor:

Yapılan bir kullanıcı araştırmasında, mağaza sahiplerinden biri koltuğundan bir düğmeyi tıkladıktan sonra koltuğundan ayrılıp vardiya masasının yüklenmesini beklerken zaman kaybetmek için kahve içmeye çalıştığını söylediğinde çok şaşırdık.

Mühendislik ekibi, araştırmalarını yaptıktan sonra kullanıcılarının birçoğunun, 10 yıl öncesinin 1 GHz Celeron M dizüstü bilgisayarı gibi düşük teknik özelliklere sahip bilgisayarlarda devasa vardiya tabloları yüklemeye çalıştığını fark etti.

Düşük teknolojili cihazlarda sonsuz döner simge.

AirSHIFT uygulaması, pahalı komut dosyaları içeren ana iş parçacığını engelliyordu ancak mühendislik ekibi, hızlı kablosuz bağlantıları olan zengin özellikli bilgisayarlarda geliştirme ve test etme yaptıkları için komut dosyalarının ne kadar pahalı olduğunu fark etmedi.

Uygulamanın çalışma zamanı etkinliğini gösteren grafik.
Kaydırma tablosu yüklenirken komut dosyalarının çalıştırılması, yükleme süresinin yaklaşık% 80'ini oluşturuyordu.

CPU ve ağ kısıtlama etkinken Chrome Geliştirici Araçları'nda performanslarının profilini oluşturduktan sonra performans optimizasyonunun gerektiği anlaşıldı. AirSHIFT bu sorunu çözmek için bir görev gücü oluşturdu. Uygulamalarını kullanıcı girişlerine daha duyarlı hale getirmek için odaklandıkları 5 noktayı burada bulabilirsiniz.

1. Büyük tabloları sanallaştırma

Vardiya tablosunun görüntülenmesi için birkaç pahalı adım gerekiyordu: Sanal DOM'un oluşturulması ve çalışanların sayısı ile zaman aralıklarıyla orantılı olarak ekranda görüntülenmesi. Örneğin, 50 çalışan üyesi olan bir restoranın aylık vardiya programını kontrol etmek istediğini varsayalım. Bu durumda tablo, 50 (üye) ile 30 (gün) çarpılır ve sonuçta 1.500 hücre bileşeni oluşturulur. Bu, özellikle düşük özellikli cihazlar için çok pahalı bir işlemdir. Aslında işler daha kötüydü. Araştırma sonucunda 200 çalışanı yöneten mağazalar olduğunu ve aylık tek bir tabloda yaklaşık 6.000 hücre bileşeninin gerekli olduğunu öğrendiler.

AirSHIFT, bu işlemin maliyetini azaltmak için vardiya tablosunu sanallaştırdı. Uygulama artık bileşenleri yalnızca görüntü alanı içine ekler ve ekran dışı bileşenlerin bağlantısını keser.

AirSHIFT'ın görüntü alanının dışındaki içeriği oluşturmak için kullanıldığını gösteren ek açıklamalı ekran görüntüsü.
Önce: Tüm üst kaydırma tablo hücreleri oluşturuluyor.
AirSHIFT'ın artık yalnızca görüntü alanında görünür olan içeriği oluşturduğunu gösteren ek açıklamalı ekran görüntüsü.
Sonra: Yalnızca görüntü alanındaki hücreler oluşturulur.

Bu durumda, karmaşık iki boyutlu ızgara tablolarının etkinleştirilmesiyle ilgili şartlar olduğundan AirSHIFT react-virtualized yöntemini kullandı. Ayrıca, uygulamayı gelecekte basit react-window kullanılacak şekilde dönüştürmenin yollarını da araştırıyorlar.

Sonuçlar

Sadece tabloyu sanallaştırmak, komut dosyası yazma süresini 6 saniye kısalttı (4 kat CPU yavaşlatma + Hızlı 3G kısıtlanan Macbook Pro ortamında). Bu, yeniden düzenleme projesindeki en etkili performans iyileştirmesiydi.

Chrome DevTools Performans panel kaydının ek açıklamalı ekran görüntüsü.
Önce: Kullanıcı girişinden sonra yaklaşık 10 saniyelik komut dosyası.
Chrome DevTools performans paneli kaydının ek açıklamalı başka bir ekran görüntüsü.
Sonra: Kullanıcı girişinden sonra 4 saniyelik komut dosyası.

2. User Timing API ile denetleme

Daha sonra AirSHIFT ekibi kullanıcı girişine göre çalışan komut dosyalarını yeniden düzenledi. Chrome Geliştirici Araçları'nın flame grafiği, ana iş parçacığında gerçekten neler olup bittiğini analiz etmeyi mümkün kılar. Ancak AirSHIFT ekibi, uygulama etkinliğini React'in yaşam döngüsüne dayalı olarak analiz etmenin daha kolay olduğunu gördü.

React 16, performans izleme bilgilerini Chrome Geliştirici Araçları'nın Zamanlamalar bölümünde görselleştirebileceğiniz User Timing API aracılığıyla sağlar. AirSHIFT, React yaşam döngüsü etkinliklerinde gereksiz mantığı bulmak için Zamanlamalar bölümünü kullandı.

Chrome Geliştirici Araçları'nın Performans panelinin Zamanlamalar bölümü.
React'in Kullanıcı Zamanlaması etkinlikleri.

Sonuçlar

AirSHIFT ekibi, her rota navigasyonundan hemen önce gereksiz bir React Ağacı Mutabakatı işleminin gerçekleştiğini keşfetmiştir. Bu, React'in gezinmelerden önce değişiklik tablosunu gereksiz bir şekilde güncellediği anlamına geliyordu. Bu soruna gereksiz bir Redux durum güncellemesi neden oluyordu. Bu dosyanın düzeltilmesi, komut dosyası oluşturma süresinden yaklaşık 750 ms tasarruf sağladı. AirSHIFT başka mikro optimizasyonlar da yaptı ve bu da nihayetinde komut dosyası yazma süresinde toplam 1 saniyelik bir azalmaya neden oldu.

3. Bileşenleri geç yükleyin ve pahalı mantığı web çalışanlarına taşıyın

AirSHIFT'ın yerleşik bir sohbet uygulaması vardır. Birçok mağaza sahibi, vardiya tablosuna bakarken personeliyle sohbet üzerinden iletişim kurar. Bu da kullanıcının tablo yüklenirken bir mesaj yazıyor olabileceği anlamına gelir. Ana iş parçacığı tabloyu oluşturan komut dosyalarıyla doluysa kullanıcı girişi kötü olabilir.

AirSHIFT, bu deneyimi iyileştirmek amacıyla artık gerçek bileşenleri geç yüklerken tablo içerikleri için yer tutucuları göstermek için React.lazy ve Suspense'i kullanıyor.

AirSHIFT ekibi ayrıca, geç yüklenen bileşenlerdeki pahalı iş mantığından bazılarını da web çalışanlarına taşıdı. Bu, ana iş parçacığının kullanıcı girişine yanıt vermeye odaklanabilmesi için serbest kalmasını sağlayarak kullanıcı girişi olumsuzluğu sorununu çözdü.

Genellikle geliştiriciler, çalışanları kullanırken karmaşık bir durumla karşı karşıya kalır ancak bu kez işin zor kısmını Comlink üstlendi. Aşağıda, AirSHIFT'ın sahip olduğu en pahalı operasyonlardan birini nasıl kullandığına ilişkin sahte kod bulunmaktadır: toplam işçilik maliyetlerini hesaplama.

App.js'de yükleme sırasında yedek içeriği göstermek için React.lazy ve Suspense'i kullanın

/** App.js */
import React, { lazy, Suspense } from 'react'

// Lazily loading the Cost component with React.lazy
const Hello = lazy(() => import('./Cost'))

const Loading = () => (
  <div>Some fallback content to show while loading</div>
)

// Showing the fallback content while loading the Cost component by Suspense
export default function App({ userInfo }) {
   return (
    <div>
      <Suspense fallback={<Loading />}>
        <Cost />
      </Suspense>
    </div>
  )
}

Maliyet bileşeninde, hesaplama mantığını yürütmek için comlink işlevini kullanın

/** Cost.js */
import React from 'react';
import { proxy } from 'comlink';

// import the workerlized calc function with comlink
const WorkerlizedCostCalc = proxy(new Worker('./WorkerlizedCostCalc.js'));
export default async function Cost({ userInfo }) {
  // execute the calculation in the worker
  const instance = await new WorkerlizedCostCalc();
  const cost = await instance.calc(userInfo);
  return <p>{cost}</p>;
}

Çalışanda çalışan hesaplama mantığını uygulayın ve comlink ile kullanıma sunun

// WorkerlizedCostCalc.js
import { expose } from 'comlink'
import { someExpensiveCalculation } from './CostCalc.js'

// Expose the new workerlized calc function with comlink
expose({
  calc(userInfo) {
    // run existing (expensive) function in the worker
    return someExpensiveCalculation(userInfo);
  }
}, self);

Sonuçlar

Denemede çalıştırdıkları mantık sınırlı olmasına rağmen AirSHIFT, JavaScript'inin yaklaşık 100 ms'sini ana iş parçacığından çalışan iş parçacığına kaydırdı (4 kat CPU kısıtlaması ile simüle edildi).

Komut dosyasının artık ana iş parçacığı yerine bir web çalışanı üzerinde gerçekleştiğini gösteren Chrome DevTools Performans paneli kaydının ekran görüntüsü.

AirSHIFT şu anda, olumsuzluğu daha da azaltmak için diğer bileşenleri geç yükleyip yükleyemeyeceğini ve web çalışanlarına daha fazla mantık yükleyebileceklerini araştırmaktadır.

4. Performans bütçesi belirleme

Bu optimizasyonların tümünü uyguladıktan sonra, uygulamanın zaman içinde iyi performans göstermeye devam etmesini sağlamak çok önemliydi. AirSHIFT artık mevcut JavaScript ve CSS dosya boyutunu aşmamak için bundlesize kullanıyor. Bu temel bütçeleri belirlemenin yanı sıra, uygulamanın ideal olmayan koşullarda bile iyi performans gösterip göstermediğini kontrol etmek için vardiya tablosu yükleme süresinin çeşitli yüzdeliklerini gösteren bir kontrol paneli oluşturdular.

  • Her Redux etkinliğinin komut dosyası tamamlanma süresi artık ölçülmektedir
  • Performans verileri Elasticsearch'te toplanır
  • Her etkinliğin 10., 25., 50. ve 75. yüzdelik dilim performansı Kibana ile görselleştirilir

AirSHIFT şu anda, 75. yüzdelik dilim kullanıcıları için 3 saniye içinde tamamlandığından emin olmak amacıyla vardiya tablosu yükleme etkinliğini izliyor. Bu bütçe şimdilik zorunlu değil. Ancak şirket, bütçesini aştığında Elasticsearch üzerinden otomatik bildirim almayı değerlendiriyor.

75. yüzdelik dilimin yaklaşık 2.500 ms., 50. yüzdelik dilimin yaklaşık 1.250 ms., 25. yüzdelik dilimin yaklaşık 750 ms. ve 10. yüzdelik dilimin yaklaşık 500 ms. içinde tamamlandığını gösteren grafik.
Günlük performans verilerini yüzdelik dilim cinsinden gösteren Kibana kontrol paneli.

Sonuçlar

Yukarıdaki grafikten, AirSHIFT'ın şu anda 75. yüzdelik dilim kullanıcıları için 3 saniyelik bütçeyi tükettiğini ve 25. yüzdelik dilim kullanıcıları için bir saniye içinde vardiya tablosunu yüklediğini görebilirsiniz. AirSHIFT artık çeşitli koşullar ve cihazlardan RUM performans verilerini alarak yeni bir özellik sürümünün gerçekten uygulamanın performansını etkileyip etkilemediğini kontrol edebiliyor.

5. Performans hackathon'ları

Tüm bu performans optimizasyonu çalışmaları önemli ve etkili olsa da mühendislik ve iş ekiplerinin işlevsel olmayan geliştirmelere öncelik vermesini sağlamak her zaman kolay değildir. Buradaki zorluklardan biri, bu performans optimizasyonlarından bazılarının planlanamamasıdır. Bunlar için deneme yapmak ve deneme yanılma yaklaşımını benimsemek gerekir.

AirSHIFT şimdi mühendislerin yalnızca performansla ilgili çalışmalara odaklanmasını sağlamak için şirket içinde 1 günlük performans hackathon'ları gerçekleştiriyor. Bu hackathon'larda tüm kısıtlamaları kaldırıyor ve mühendislerin yaratıcılığına saygı gösteriyorlar. Bu nedenle, hıza katkıda bulunan her türlü uygulama, değerlendirilmeye değer. AirSHIFT, hackathon'u hızlandırmak için grubu küçük ekiplere ayırır ve her ekip Lighthouse performans puanında en büyük artışı kimin elde edebileceğini görmek için yarışır. Ekipler rekabet ediyor. 🔥

Hackathon fotoğrafları.

Sonuçlar

Hackathon yaklaşımı onlar için iyi sonuç veriyor.

  • Performans sorunları, hackathon sırasında farklı yaklaşımları deneyerek ve her birini Lighthouse ile ölçerek kolayca tespit edilebilir.
  • Hackathon'dan sonra ekibi üretim sürümü için hangi optimizasyona öncelik vermeleri gerektiğine ikna etmek oldukça kolay.
  • Aynı zamanda hızın önemini savunmanın da etkili bir yoludur. Her katılımcı, kodlama şekliniz ve bunun performans üzerindeki etkisi arasındaki ilişkiyi anlayabilir.

Bunun iyi bir yan etkisi de Recruit bünyesindeki diğer birçok mühendislik ekibinin bu uygulamalı yaklaşımla ilgilenmesi ve AirSHIFT ekibinin şu anda şirket içinde birden fazla hız hackathon'una yardımcı olmasıydı.

Özet

AirSHIFT'ın bu optimizasyonlar üzerinde çalışması kesinlikle en kolay yolculuğu değildi, ancak kesinlikle karşılığını aldı. AirSHIFT şimdi vardiya tablosunu 1,5 saniye içinde ortanca değer olarak yüklüyor.Bu da, mevcut performansa kıyasla 6 kat iyileşme anlamına geliyor.

Performans optimizasyonları kullanıma sunulduktan sonra bir kullanıcı şunu dedi:

vardiya tablosunun hızlı bir şekilde yüklenmesini sağladığınız için çok teşekkür ederiz. Vardiyalı işleri düzenlemek artık çok daha verimli.