React’ta Yüksek Hızda Veri İşleme Taktikleri

React'ta Yüksek Hızda Veri İşleme: React'ta Yüksek Hızda Veri İşleme React'ta Yüksek Hızda Veri İşleme kapsamında, React'ta Yüksek Hızda Veri İşleme kapsamında, React birçok konuda harikadır. Ancak saniyede binlerce veri noktasını iletmeyi denediyseniz, React'ın bir itfaiye…

2
Paylaş
React’ta Yüksek Hızda Veri İşleme Taktikleri

React'ta Yüksek Hızda Veri İşleme: React'ta Yüksek Hızda Veri İşleme

React'ta Yüksek Hızda Veri İşleme kapsamında, React'ta Yüksek Hızda Veri İşleme kapsamında, React birçok konuda harikadır. Ancak saniyede binlerce veri noktasını iletmeyi denediyseniz, React’ın bir itfaiye hortumu olmadığını hemen anlayacaksınız. Daha çok bahçe hortumuna benziyor. Çok fazla zorlamayı deneyin; çimler sular altında kalır (DOM’niz) ya da boru patlar (uygulamanız). İlkiyle eşleşen ikinci bir gözlem daha var. Dizüstü bilgisayarınızda 8 ila 16 CPU çekirdeği bulunur.

React'ta Yüksek Hızda Veri İşleme nedir, nelere dikkat edilir

React'ta Yüksek Hızda Veri İşleme ile ilgili temel noktaları aşağıda adım adım özetliyoruz.

React'ta Yüksek Hızda Veri İşleme kapsamında, React'ta Yüksek Hızda Veri İşleme kapsamında, React uygulamanız neredeyse her zaman bunlardan birini kullanır. Ana iş parçacığı JavaScript’i, DOM’u, düzeni ve boyama kurulumunu yönetir. Ana iş parçacığı 60 fps çerçeve bütçesini korumaya çalışırken diğer çekirdekler boşta duruyor. Her iki sorun da aynı şekle sahiptir: React’ı etkin yolun dışında tutmanız ve birden fazla iş parçacığı kullanmanız gerekir.

React'ta Yüksek Hızda Veri İşleme kapsamında, React'ta Yüksek Hızda Veri İşleme kapsamında, Sizi oraya götüren kalıplar aynı zamanda Figma’nın tuval motorunun, Bloomberg’in ticaret kontrol panellerinin ve gördüğünüz her biyosinyal görüntüleyicinin arkasındaki kalıplardır. Bir projede, her biri saniyede yaklaşık 1000 veri noktası gönderen 19 EEG (beyin dalgası) kanalını görselleştirmem gerekiyordu. Bu saniyede neredeyse 19.000 güncelleme demektir.

Tasarım ve teknik ayrıntılar

React'ta Yüksek Hızda Veri İşleme kapsamında, React'ta Yüksek Hızda Veri İşleme kapsamında, Bunların hepsini doğrudan React’a aktarırsanız kullanıcı arayüzü yavaşlamaz. Dramatik bir şekilde bayılıyor. Bu makale, üzerinde durduğum uçtan uca mimaridir: halka arabellekleri, çalışanlar, paylaşılan bellek, ana dışı işleme ve çok saatlik sürekli yüke dayanabilen belirli modeller. İçindekiler Önkoşullar Bunu Zaten Kim Yapıyor?

React'ta Yüksek Hızda Veri İşleme kapsamında, React'ta Yüksek Hızda Veri İşleme kapsamında, 1kHz Matematik Her Zamanki Yerinde Zihinsel Model Yanlış Gidiyor: Hava Trafik Kontrolü Artı Bir Mutfak Tugayı Adım 1: Örnekleri Reaksiyon Durumuna Koymayı Durdurun Adım 2: Şekli Değerlerden Ayırın Adım 3: Ağır İşi Ana İş Parçasından Uzaklaştırın Adım 4: Ana İşlemi OffscreenCanvas ile Kapatın Adım 5: Çizmeden Önce Yok Edin Adım 6: Harici Bir Oluşturucuyu Sarın Adım 7: Kanvas Yeterli Olmadığında, WebGL’ye Ulaşın Adım 8: Belleği Düz Tutun Adım 9: Planlama Stratejileri Adım 10: Sürdürülebilir Performansı Ölçün Örnek Olay İncelemesi: 19 EEG Kanalı Karşılaştırmalar: Tek İş Parçacığı mı Çok İş Parçacığı mı COOP/COEP Yakalama Üretimi Dengeleri Bu Şekilde mi Oluşturmalısınız?

React'ta Yüksek Hızda Veri İşleme

React'ta Yüksek Hızda Veri İşleme kapsamında, Sonlandırma Referanslar Önkoşullar Bu makaleden en iyi şekilde yararlanmak için şunları isteyeceksiniz: React 18 veya 19 hakkında çalışma bilgisi. useState, useEffect, useRef ve montaj ile yeniden oluşturma arasındaki fark konusunda rahat olmalısınız. TypeScript’in temelleri. Çoğu örnek TypeScript’tedir. Yazı ek açıklamalarını durmadan okuyabilmelisiniz.

Bugünden bakınca ne kadar güvenilir?

Tarayıcının ana iş parçacığı ve olay döngüsünün kabaca anlaşılması. Bir Web Çalışanı yazmanıza gerek yoktur, ancak “ana iş parçacığını engellemenin” ne anlama geldiğini bilmek 3. Adımı kolaylaştıracaktır. Canvas 2D veya grafik kütüphanesine aşina olmak bir zorunluluk değil, bir artıdır. Tuval üzerine herhangi bir şey çizdiyseniz hazırsınız. Modern Chrome veya Edge’i çalıştırabilen bir dizüstü bilgisayar.

Örnekler, Chromium tabanlı bir göz atmaya ihtiyaç duyan SharedArrayBuffer, OffscreenCanvas ve Atomics’e dayanmaktadır. r ve çapraz köken izolasyonu (makalenin ilerleyen bölümlerinde ele alınacaktır). Web Çalışanları, halka arabellekleri veya WebGL ile ilgili önceden deneyime ihtiyacınız yoktur. Bu makale her birini gerçek bir sorun bağlamında tanıtmaktadır. Bunu Zaten Kim Yapıyor?

Bu makaledeki modeller deneysel değildir. Bunlar, yüksek frekanslı verileri alıp işleyen üretim uygulamalarının arkasındaki mimaridir: Ticaret ve finans kontrol panelleri (Bloomberg, Hyperliquid, dYdX, tüm ciddi piyasa izleyicileri), tuvalle oluşturulmuş ızgaralar aracılığıyla saniyede binlerce fiyat adımını zorlar. Figma, tuval motorunun tamamını WebAssembly’de bir işçinin içinde çalıştırır.

Okuyucu için pratik anlamı

Ana iş parçacığı yalnızca Chrome için React’i oluşturur. Google Dokümanlar ve Microsoft Loop, belge modellerini, projeksiyon olarak DOM ile çalışanlarda çalıştırır. LightningChart, uPlot, Plotly ve ECharts gibi grafik kitaplıkları Canvas veya WebGL üzerinde çizim yapar ve React’ı bir sarmalayıcı olarak görür.

Biyosinyal, EKG, EEG ve hareket yakalama uygulamaları örnekleri rutin olarak 1kHz veya daha yüksek hızlarda işler ve bunları canlı grafiklere aktarır. Gözlemlenebilirlik ve APM araçları (Datadog live tail, Grafana gerçek zamanlı paneller), sekmelerin yanıt vermesini sağlamak için alımı işlemeden ayırır. Ses düzenleyicileri ve görselleştiricilerin yanı sıra dalga biçimi ekranıyla Web Ses API’sini kullanan her şey.

transformatörler.js ve ONNX Runtime Web, varsayılan olarak çalışanlara makine öğrenimi çıkarımı yerleştirir. Farklı alanlar, aynı numara: React nadiren değişen şeylerin sahibi olur, yenileme sırasında değişen şeyler başka bir şeyin sahibi olur oran ve ana iş parçacığı olmayan iş parçacıkları üzerinde ağır işler meydana gelir. 1kHz Matematik Sorunu somutlaştıracak bazı rakamlar. Her 1 ms’de bir örnek gelir.

60Hz ekran her 16,67 ms’de bir yenilenir. Yani tek bir karede akış başına yaklaşık 16 ila 17 örnek alacaksınız. 19 aktif akışla (EEG durumu), bu, kare başına 300 ila 320 örnek anlamına gelir. Her örnekte State’i ayarlarsanız React, saniyede yaklaşık 19.000 görüntü oluşturma işlemi gerçekleştirmeye çalışır. Yapamaz, dolayısıyla kareleri atlar. Kullanıcı arayüzü tekliyor ve dizüstü bilgisayar fanlarınız havalanıyor.

~320 örneklik bir toplu iş ile State’i kare başına bir kez ayarlarsanız, React saniyede 60 işleme yapar ki bu da kolaydır. Bu tek yeniden çerçeve tüm püf noktasıdır ve aşağıdaki her adımda yankılanacaktır. Genellikle Nerede Yanlış Yapılır İşte çoğu gerçek zamanlı React uygulamasında bunu ilk denediklerinde gördüğüm kod sürümü. Makul görünüyor.

Bu aynı zamanda ekibin önümüzdeki iki haftayı takip ederek geçireceği her türlü saçmalığın da kaynağıdır.

“react” öğesinden { useEffect, useState } dosyasını içe aktarın; varsayılan işlevi dışa aktar NaiveChart({ soket }) { const [veri, setData] = useState([]); useEffect(() => { soket.on(“yeniNokta”, (nokta: sayı) => { setData((önceki) => […önceki, nokta]); // her seferinde yeniden oluşturulur }); }, [soket]);

{data.length} nokta
döndür; } Yedi satıra bölünmüş üç sorun: Gelen her örnek bir yeniden oluşturmayı tetikler: 1kHz’de bu, saniyede 1.000 oluşturma anlamına gelir.

Tepki asla g olmadı bundan mutlu olmak için. […prev, point] her basışta yeni bir dizi tahsis eder: 1kHz’de bu her milisaniyede yeni bir dizidir ve bunların tamamını çöp toplayıcının temizlemesi gerekir. Yığın artar, GC duraklamaları uzar, fan devreye girer.

Dizide üst sınır yoktur: Bunu bir saat boyunca çalıştırdığınızda hafızanızda 3,6 milyon sayı olur ve React’ın her oluşturmada bunların hepsini dikkate alması gerekir. Düzeltme tek bir numara değil. Bu, her biri bu arıza modlarından birine hitap eden ve sonuçta ana iş parçacığının tek iş parçacığı olmasıyla ilgili daha derin bir sorunu ele alan küçük bir yığındır.

Zihinsel Model: Hava Trafik Kontrolü Artı Mutfak Tugayı Kodun önünde parçaları düz tutacak iki metafor var. Birincisi, hava trafik kontrolü: Üç rol, bir havaalanı. Kontrol kulesi (mağazanız) her uçağı (her numuneyi) görür ve nerede olduğunu takip eder. Yer ekibi (React) pistleri ve kapıları kurar: uçakların kullandığı düzen. Pilotlar (beraberlik döngüsü) aslında uçuyor.

Temizlemek için kuleye bakıyorlar ve birkaç saniyede bir harekete geçiyorlar. Kontrol kulesi, uçak her hareket ettiğinde yer ekibinden kapıyı çekmez. Sadece verileri tutar. Yer ekibi, program değiştiğinde kapıları yeniden düzenler ki bu nadir görülen bir durumdur. Pilotlar kulenin verilerine göre sürekli olarak kendi hızlarına göre hareket ederler. İkincisi, bir mutfak ekibi: Yoğun saatlerde bir restoran mutfağı.

Bir baş aşçı her yemeği yapamaz. Klasik tugayın statüsü var iyonlar: sos, balık, hamur işi, garde yemliği, kaplama ve servis. Her istasyon yemeğin bir dilimine sahiptir. Hızlandırıcı zamanlamayı koordine eder. Hızlandırıcı sizin ana konunuzdur. İstasyonlar sizin işçilerinizdir. Kaplama penceresi paylaşılan hafızanızdır. Masalara giden tabaklar sizin işlenmiş çerçevelerinizdir.

Her şeyi seri olarak yapmaya çalışan tek bir şef, yalnızca ana iş parçacıklı ön yüzünüzdür. Bir tugay sizin işçi temelli olanınızdır. Ekip daha hızlıdır çünkü kesmeler, soslar ve kızartmalar paralel olarak gerçekleşir, herhangi bir aşçı solistten daha hızlı olduğu için değil. Hızlandırıcı yemek pişirmez, orkestrasyon yapar. Aşağıdaki her şey bu iki fikrin özel bir uygulamasıdır.

Adım 1: Örnekleri React Durumuna Koymayı Durdurun Gerçek zamanlı React uygulamalarındaki en büyük hata, her örneği durum olarak ele almaktır ki öyle değildir. Durum, hangi bileşenlerin var olduğunu ve bunların nasıl düzenleneceğini belirleyen şeydir. Canlı bir olay örgüsü bir bileşendir. Üzerinde kayan 60.000 örnek, 60.000 durum parçası değil. Onlar tek tampon. React’in dışında yaşayan bir mağaza istiyorsunuz.

Yazılı bir dizi üzerindeki halka arabelleği size sabit zamanlı eklemeler ve sınırlı bir yığın sağlar: type Listener = () => void; dışa aktarma işlevi createSampleStore(kapasite: sayı) { const buf = new Float32Array(kapasite); baş = 0 olsun; boyut = 0 olsun; const dinleyicileri = new Set(); dönüş { push(örnek: sayı) { buf[baş] = örnek; kafa = (kafa + 1) % kapasite; eğer (boyut < kapasite) boyut++; }, pushBatch(örnekler: Float32Array) { for (let i = 0; i < örnekler.uzunluk; i++) { buf[baş] = örnekler[i]; kafa = (kafa + 1) % kapasite; if (boyut < kapasite) size++; } }, oku(): Float32Array { if (size listeners.delete(l); }, }; } Burada olmayana dikkat edin: useState yok, ayarlayıcı yok, herhangi bir React yok.

Bu sadece basit bir JavaScript. Mağaza saniyede bir milyon itmeyi kabul edebilir ve React bunu umursamayacaktır çünkü React d değildir. İşte halka tampon mekaniğinin görselleştirilmiş hali: Her itişte kafa ilerlemelerimiz var ve kapasiteyle sarıyoruz. Okumalar, son N numunenin bir penceresini kronolojik sıraya göre çeker. Sonuç, sabit zaman ve sınırlı bir yığındır.

Henüz yazılan bir arabellek istemiyorsanız, daha basit bir geçici çözüm, dönen pencereyi durum yerine bir ref’e koymaktır: import { useEffect, useRef } from “react”; varsayılan işlevi dışa aktar RefChart({ soket }) { const bufferRef = useRef([]); useEffect(() => { soket.on(“yeniNokta”, (nokta: sayı) => { bufferRef.current.push(nokta); if (bufferRef.current.length > 1000) { bufferRef.current.shift(); } }); }, [soket]); return

Akış {bufferRef.current.length} nokta
; } Bu, “N’den 10 kat daha hızlıdır aiveChart, hala harika değil” sürümü.

Oluşturma her basışta tetiklenmez, ancak başka bir şey yeniden oluşturulmadıkça güncellemeleri de göremezsiniz. Gerçek çizim için, ref’i requestAnimationFrame çizim döngüsüyle eşleştirin (bkz. Adım 2). Adım 2: Şekli Değerlerden Ayırın React, kullanıcı arayüzünün şekli değiştiğinde oluşturulur. Yeni çizim? Yeniden oluşturma. Kaldırılan çizim? Yeniden oluşturma. Satırdan çubuğa mı geçildi? Yeniden oluşturma.

Bunların hiçbiri olmuyor 1000Hz’de. Kullanıcı bir şeyi tıklattığında dakikada birkaç kez gerçekleşir. Her grafiğin içindeki değerler, React’e asla dokunmamalıdır.

const canvasRef = useRef(null); useEffect(() => { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext(“2d”!); raf = 0 olsun; const beraberlik = () => { const örnekleri =store.read(); DrawSeries(ctx, örnekler); raf = requestAnimationFrame(draw); }; raf = requestAnimationFrame(draw); return () => cancelAnimationFrame(raf); }, [mağaza]); return ; } React bu bileşeni bir kez işler.

UseEffect bir kez çalışır. requestAnimationFrame döngüsü her karede depodan okur. Mağaza, kaynağın yönetebileceği herhangi bir oranda itilebilir. Kullanıcı, kaynağın saniyede 100 örnek mi yoksa 100.000 örnek mi gönderdiğine bakılmaksızın 60 fps’lik düzgün bir çizgi görür. Sam’e telgraf çekme içgüdüsü useState’e giriş yanlıştır, bu yüzden buna direnin.

İhtiyaç Duyduğunuzda Seçici Abonelikler Döngüde Tepki Verme Bazen bir bileşen gerçekten verilere bağlıdır (özet istatistikler, eksen etiketleri veya canlı değer rozeti). Bunun için, yalnızca önemseyen bileşenlerin yeniden oluşturulması için seçici aboneliklere sahip bir mağaza kullanın.

Zustand bunu önemsiz kılıyor: import { create } from “zustand”; const useDataStore = create void }>((set) => ({ en son: boş, setLatest: (v) => set({ en son: v }), })); function En SonBadge() { // Yalnızca en son değişiklikler olduğunda yeniden oluşturulur, diğer depolama alanları değiştirildiğinde değil.

const en son = useDataStore((state) => state.latest); return

En Son: {latest?.toFixed(2)
; } Bunu, yazma işlemleri sırasında RAF’ın birleşmesi ile eşleştirdiğinizde (örnek başına bir kez değil, çerçeve başına bir kez setLatest’i çağırın) ve veri hızı ne olursa olsun, 60 fps’de sorunsuz bir şekilde güncellenen bir React bileşeni elde edersiniz.

useSyncExternalStore yerel eşdeğeridir ve yukarıdaki halka arabelleği de dahil olmak üzere herhangi bir pub-sub deposunda çalışır. Ekibiniz için hangisi daha hafif geliyorsa onu kullanın. Adım 3: Ağır İşi Ana İş Parçasından Uzaklaştırın Store ve zorunlu çekme döngüsü, React’in darboğaza olan katkısını ele alır. Ana iş parçacığının kendisi hala tüm alma, ayrıştırma ve matematik işlemlerini yapıyor.

Akış başına saniyede ~50.000 örneği aşan her şeyin daha fazlasına ihtiyacı vardır. Tarayıcı size dört kaçış yolu sunar: Web Çalışanları, aktarım mümkün nesneler, SharedArrayBuffer + Atomics ve OffscreenCanvas. Her biri belirli bir sorunu çözer. Ana iş parçacığı JavaScript’i, DOM’u, düzeni ve boyama kurulumunu çalıştırır. Çalışanlar, kendi olay döngülerine sahip yalıtılmış JavaScript bağlamlarıdır.

DOM’a dokunamazlar, varsayılan olarak belleği paylaşamazlar ve siz aktarmadığınız sürece her çapraz iş parçacığı mesajı eşzamansızdır ve kopyalanır. Bu modele göre tasarım yaparken üç özellik önemlidir: İşçiler DOM’a dokunamaz: Önemli olan da bu. Saf JavaScript çalıştırıyorlar. Veri çalışması, ağ ayrıştırma, matematik, codec’ler ve makine öğrenimi çıkarımı için mükemmeldir.

İletişim eşzamansızdır: Bir işlevin ortasında okunacak paylaşılan değişken yoktur. API’leri istekler ve olaylar etrafında planlayın. Aktarmadığınız veya paylaşmadığınız sürece veriler kopyalanır: Yapılandırılmış klon varsayılandır, aktarılabilir nesneler kopyayı atlar ve SharedArrayBuffer bunu kalıcı olarak atlar.

Uygulamada Adanmış İşçiler İşte alım için minimum işçi sayısı: //worker.ts self.onmessage = (olay) => { const { örnekler } = olay.veri; // Kod çöz, filtrele, yok et. Ana başlık bunların hiçbirini görmüyor.

const özeti = computeStats(örnekler); postMessage(özet); }; // ana iş parçacığı “react” öğesinden { useEffect, useRef }’i içe aktarın; varsayılan işlevi dışa aktar WorkerChart({ soket, mağaza }) { const işçiRef = useRef(); useEffect(() => { WorkerRef.current = new Worker(new URL(“./worker.ts”, import.meta.url), { şunu yazın: “modül”, }); işçiRef.akım

Ek okuma: MDN Web Docs

Editörün Notu

Yüksek performans için React uygulamalarında iş yükünü ana iş parçacığından ayırarak çoklu çekirdek kullanımını artırmak, kullanıcı deneyimini ve veri işleme hızını önemli ölçüde iyileştirir.

Emre Demir
Yazar

Yazılım Editörü

Yazılım editörü ve full-stack geliştirici. Uygulama incelemeleri, kodlama rehberleri ve verimlilik araçları üzerine yazıyor. Açık kaynak projelere katkıda bulunuyor; karmaşık konuları yeni başlayanların anlayacağı şekilde anlatmaya özen gösteriyor.

Tüm yazıları gör →