Mimari

Sıradan bir dizüstü bilgisayarda nasıl hızlı kalıyor.

Alım satım ekranları ağırdır: uzun geçmişler, hiç durmayan tick’ler, bir sayfada çok sayıda grafik. TradeCanvas her karenin gerektirdiği kadar az iş yapar; ana iş parçacığında, üçüncü taraf kod olmadan. Bu sayfa bunun nasıl yapıldığını ve hâlâ nerede iyileştirildiğini gösterir.

Yapım aşamasında: motor yayına alınacak kadar hızlı, ama henüz olacağı kadar hızlı değil. Son bölüm, kaldığını bildiğimiz işleri listeler.

01

Küçük paketler, tek yön

Her paket yalnızca altındakilere bağlıdır. Sayfanızda TradeCanvas dışından hiçbir şey çalışmaz: framework bileşenleri React, Vue veya Svelte’i eş bağımlılık (peer) olarak alır ve WebGL oluşturucu, yalnızca bir grafik istediğinde yüklenen ayrı bir parçadır.

0 üçüncü taraf çalışma zamanı bağımlılığı

02

Bir tick’in yolu

Bir fiyat akışınızdan gelir ve tek bir karede ekrana ulaşır. Her aşama yalnızca değişen kısmı işler.

  1. 1AkışınızDataAdapterWebSocket, REST, bir broker: geçmişi ve akışı olan her şey.
  2. 2Akış yöneticisiStreamManagerÖnce geçmiş, sonra canlı. Eski bir isteğin yanıtları atılır; sessiz kalan bir akış 30 sn içinde fark edilir.
  3. 3Tick toplayıcıTickAggregatorTick’ler 1.000’lik bir halka arabelleğine girer ve kendi zaman diliminin barına katlanır.
  4. 4GöstergelerIndicatorEngineSerinin başından değil, son bardan yeniden hesaplanır.
  5. 5Görünüm alanıViewportYalnızca ekrandaki barlar dolaşılır; fiyat ölçeği yalnızca onlardan gelir.
  6. 6Çizim döngüsüRenderLoopKaç tick gelirse gelsin, sahne animasyon karesi başına en fazla bir kez çizilir.
  7. 7Canvas 2D veya WebGLRenderEngineİki canvas ve WebGL açıkken altlarında bir GPU canvas’ı.
03

Bir tick tüm geçmişe değil, tek bir bara mal olur

Bir tick son barı değiştirdiğinde her gösterge seriyi yeniden hesaplamak yerine o bardan (ve formülünün geriye baktığı birkaç önceki bardan) devam eder. Hatırladığı barlar artık eşleşmiyorsa tam yeniden hesaplamaya döner, böylece bir düzeltme asla kaçırılmaz.

Yaklaşık 20 göstergenin kendi artımlı güncellemesi var ve 31 tanesi daha nokta nokta devam eden bir temel üzerine kurulu. Başka bir göstergenin çizgisini okuyan göstergeler de devam eder.

0 / 64 Dört göstergeyle 100.000 barda ölçüldü: tick başına yaklaşık 0,001 ms
04

Uzaklaştırıldığında: piksel başına bir sütun

Barlar bir pikselden daralınca her birini çizmek, gözün göremeyeceği bir iş harcar. Mumlar, barlar, yüksek-düşük ve hacim, piksel başına bir sütun olarak çizilir; altındaki barların ilk açılışı, en yüksek yükseği, en düşük düşüğü ve son kapanışıyla. Çizgiler ve alanlar piksel başına yaklaşık iki nokta tutar (LTTB); gösterge çizgileri ve bantları piksel sütunu başına tek aralık çizer.

görünen bar
313
piksel başına bar
0,39
çizilen şekil
313

Bir bar asla bir CSS pikselinin dörtte birinden dar olmaz; bu yüzden bir milyon bar tutan bir grafik sonuna kadar uzaklaştırıldığında piksel başına en fazla yaklaşık dört bar gösterir: 1.600 px’lik bir grafikte yaklaşık 6.400. Geri kalanın içinde kaydırmak, bir milyon barlık kıyaslamanın ölçtüğü şeydir.

05

İki canvas, böylece üzerine gelmek neredeyse hiçbir şeye mal olmaz

Sahne (ızgara, seriler, göstergeler, çizimler, emirler) bir canvas’ta durur; artı imleç, açıklama, eksen etiketleri ve geri sayım onun üstündeki ince bir canvas’ta. Fareyi hareket ettirmek yalnızca üsttekini yeniden çizer. Bir veri güncellemesi sahneyi bir sonraki karede bir kez yeniden çizer.

Tam boyutlu her canvas tarayıcıya kare başına bir harmanlamaya mal olur, bu yüzden motor onları az tutar: yalnızca 2D çizim için bir arka canvas, yalnızca bir şeyin ona ihtiyacı olduğu sürece var olur.

06

WebGL, yeniden yazarak değil kaydederek

Grafik, Canvas 2D çağrılarıyla çizer. WebGL açıkken bu çağrılar, yolları, dolguları ve kontürleri cihaz piksellerinde GPU komutlarına çeviren bir kaydediciye gider. GPU’nun aynı şekilde çizemediği her şey sırasıyla Canvas 2D’de kalır, böylece görüntü her iki yolla da aynıdır.

  • renderer: 'auto' tarayıcıdan büyük bir performans uyarısı taşımayan bir bağlam ister; böylece WebGL’i yazılımda çalışacak bir makine Canvas 2D’de kalır.
  • Bir sayfada en fazla 8 grafik bir WebGL bağlamı tutar (setMaxWebGLCharts); diğerleri bir kuyrukta bekler ve Canvas 2D ile çizer.
  • GPU bağlamı düşürürse grafik Canvas 2D ile devam eder ve bağlam geri geldiğinde WebGL üzerinde yeniden kurulur.
  • Mumlar, gölgelendiricilerde ve CPU’da aynı kuralla tam cihaz piksellerine yuvarlanır, böylece her iki oluşturucu da onları aynı piksellere yerleştirir.
07

Zayıf makineler için yapıldı

  • Varsayılan olarak Canvas 2DWebGL, daha fazla cihazda ölçülene kadar isteğe bağlıdır. Yüksek piksel oranında tümleşik grafikte darboğaz çizim değil, tarayıcının kendi birleştirme işidir.
  • Kare başına tek yeniden boyutlandırmaYeniden boyutlandırma olayları kare başına bire toplanır ve değişmeyen bir boyut hiçbir şey yapmaz.
  • Sayfa sayfa geçmişGeriye kaydırdıkça eski barlar 500’er yüklenir, her seferinde tek istekle ve bir hatadan sonra geri çekilerek.
  • Yükleme yanıp sönmesi yokYükleme perdesi 200 ms bekler, böylece hızlı bir sembol değişimi asla göz kırpmaz.
  • İndirmesi küçükHeadless grafik gzip’li 176 KB, eksiksiz widget 315 KB, WebGL oluşturucu kullanıldığında 18 KB daha.
  • Yerinde güncellenen ekranlarbo-grid fiyat ekranı tick’leri kare başına tek bir güncellemede birleştirir ve yalnızca değişen hücreleri yeniden çizer.
08

Hâlâ iyileştirdiklerimiz

Motor bitmedi. Bunlar kaynaktan bildiğimiz maliyetler ve üzerinde çalışılacak sıradaki işler.

  1. Göstergeler kare başına bir kez değil, her bar güncellemesinde güncellenir: kare başına çok tick gönderen bir akış, çizdiğinden daha sık yeniden hesaplar.
  2. Barlar bir nesne dizisi olarak tutulur. Türlendirilmiş dizilerden oluşan sütunlu bir depo daha az bellek kullanır ve çok uzun geçmişlerde daha hızlı dolaşılır.
  3. Her şey ana iş parçacığında çalışır. Gösterge hesabı için bir worker kodda var ama henüz grafiğe bağlanmadı.
  4. Derinlik ısı haritası anlık görüntülerini düz bir dizide tutar ve her karede maksimumu için her seviyeyi yeniden tarar; hacim profili kovalarını her çizimde yeniden ayırır.
  5. Bazı nesneler hâlâ her karede ayrılır (yollar, küçük diziler), bu da çöp toplayıcıya iş çıkarır.
  6. Tümleşik grafikte 2560×1400 ve 2 piksel oranında yalnızca birleştirme yaklaşık 23 ms sürer, bu yüzden orada WebGL kareleri ortalama 29 ms’dir.
Kendi bilgisayarınızda ölçün →Denetim sayfası bu sahneleri tarayıcınızda çalıştırır: Canvas 2D ve WebGL’de bir milyon bar, 100.000 barda canlı tick’ler ve 1.000 sembollü bir ekran.