Wie es auf einem gewöhnlichen Laptop schnell bleibt.
Trading-Oberflächen sind schwer: lange Historien, Ticks ohne Pause, viele Charts auf einer Seite. TradeCanvas erledigt nur so viel Arbeit, wie jedes Bild braucht, im Hauptthread, ohne Code von Drittanbietern. Diese Seite zeigt, wie, und wo noch daran gearbeitet wird.
In Arbeit: Die Engine ist schnell genug für den Einsatz, aber noch nicht so schnell, wie sie werden wird. Der letzte Abschnitt listet auf, was noch offen ist.
Kleine Pakete, eine Richtung
Jedes Paket hängt nur von denen darunter ab. Nichts außerhalb von TradeCanvas läuft auf Ihrer Seite: Die Framework-Komponenten nehmen React, Vue oder Svelte als Peer-Abhängigkeit, und der WebGL-Renderer ist ein eigener Chunk, der erst geladen wird, wenn ein Chart ihn anfordert.
0 Laufzeitabhängigkeiten von Drittanbietern
Der Weg eines Ticks
Ein Kurs kommt aus Ihrem Feed und erreicht den Bildschirm in einem Bild. Jede Stufe erledigt nur den Teil, der sich geändert hat.
- 1Ihr Feed
DataAdapterWebSocket, REST, ein Broker: alles mit Historie und Stream. - 2Stream-Manager
StreamManagerErst die Historie, dann live. Antworten auf eine veraltete Anfrage werden verworfen; ein verstummter Feed fällt innerhalb von 30 s auf. - 3Tick-Aggregator
TickAggregatorTicks landen in einem Ringpuffer für 1.000 und werden in die Kerze ihrer Zeiteinheit eingerechnet. - 4Indikatoren
IndicatorEngineAb der letzten Kerze neu berechnet, nicht ab dem Anfang der Serie. - 5Viewport
ViewportDurchlaufen werden nur die Kerzen auf dem Bildschirm; die Preisskala ergibt sich allein aus ihnen. - 6Render-Schleife
RenderLoopWie viele Ticks auch ankommen, die Szene wird höchstens einmal pro Animationsbild gezeichnet. - 7Canvas 2D oder WebGL
RenderEngineZwei Canvas und darunter eine GPU-Canvas, wenn WebGL aktiv ist.
Ein Tick kostet eine Kerze, nicht die ganze Historie
Ändert ein Tick die letzte Kerze, rechnet jeder Indikator ab dieser Kerze weiter (und ab den wenigen davor, auf die seine Formel zurückblickt), statt die Serie neu zu berechnen. Passen die Kerzen, die er sich merkt, nicht mehr, fällt er auf eine vollständige Neuberechnung zurück, damit keine Korrektur verloren geht.
Etwa 20 Indikatoren haben ein eigenes inkrementelles Update, und 31 weitere bauen auf einer Basis auf, die Punkt für Punkt weiterrechnet. Indikatoren, die die Linie eines anderen Indikators lesen, rechnen ebenfalls weiter.
Herausgezoomt: eine Spalte pro Pixel
Werden Kerzen schmaler als ein Pixel, verschwendet es Arbeit, jede einzeln zu zeichnen, denn das Auge sieht es nicht. Kerzen, Balken, Hoch-Tief und Volumen werden als eine Spalte pro Pixel gezeichnet, mit dem ersten Eröffnungskurs, dem höchsten Hoch, dem tiefsten Tief und dem letzten Schlusskurs der Kerzen darunter. Linien und Flächen behalten etwa zwei Punkte pro Pixel (LTTB); Indikatorlinien und Bänder zeichnen einen Strich pro Pixelspalte.
- Kerzen im Bild
- 313
- Kerzen pro Pixel
- 0,39
- gezeichnete Formen
- 313
Eine Kerze ist nie schmaler als ein Viertel eines CSS-Pixels, daher zeigt ein Chart mit einer Million Kerzen ganz herausgezoomt höchstens etwa vier Kerzen pro Pixel: etwa 6.400 auf einem 1.600 px breiten Chart. Das Verschieben durch den Rest misst der Benchmark mit einer Million Kerzen.
Zwei Canvas, damit ein Hover fast nichts kostet
Die Szene (Raster, Serie, Indikatoren, Zeichnungen, Orders) liegt auf einer Canvas; Fadenkreuz, Legende, Achsenbeschriftungen und Countdown liegen auf einer schlanken Canvas darüber. Eine Mausbewegung zeichnet nur die obere neu. Ein Daten-Update zeichnet die Szene einmal neu, im nächsten Bild.
Jede bildschirmgroße Canvas kostet den Browser ein Überblenden pro Bild, daher hält die Engine ihre Zahl klein: Eine hintere Canvas für reines 2D-Zeichnen gibt es nur, solange etwas sie braucht.
WebGL durch Aufzeichnen, nicht durch Umschreiben
Der Chart zeichnet mit Canvas-2D-Aufrufen. Mit aktivem WebGL gehen diese Aufrufe an einen Recorder, der Pfade, Füllungen und Striche in GPU-Befehle in Gerätepixeln umsetzt. Was die GPU nicht identisch zeichnen kann, bleibt der Reihe nach auf Canvas 2D, sodass das Bild in beiden Fällen gleich ist.
- Pfade, Füllungen und Striche
- Kerzen, Volumen und Raster als instanzierte Draw-Calls
- die Serie in einem Float32Array, sechs Floats pro Kerze; ein Tick schreibt nur das Ende neu
- Text
- Bilder und Muster
- Schatten, Filter, ungewöhnliche Clips
- alles nach dem ersten Schritt, den die GPU nicht gehen kann
renderer: 'auto'fragt den Browser nach einem Kontext ohne größere Leistungseinbußen, daher bleibt ein Rechner, dessen WebGL in Software laufen würde, bei Canvas 2D.- Höchstens 8 Charts pro Seite halten einen WebGL-Kontext (
setMaxWebGLCharts); die übrigen warten in einer Warteschlange und zeichnen mit Canvas 2D. - Verliert die GPU den Kontext, zeichnet der Chart mit Canvas 2D weiter und baut sich auf WebGL neu auf, sobald der Kontext zurückkommt.
- Kerzen werden in den Shadern und auf der CPU nach derselben Regel auf ganze Gerätepixel gerundet, daher setzen beide Renderer sie auf dieselben Pixel.
Gebaut für schwache Rechner
- Standardmäßig Canvas 2DWebGL ist optional, bis es auf mehr Geräten gemessen wurde. Auf integrierter Grafik mit hohem Pixelverhältnis ist das Compositing des Browsers selbst der Engpass, nicht das Zeichnen.
- Eine Größenänderung pro BildResize-Events werden zu einem pro Bild gebündelt, und eine unveränderte Größe bewirkt nichts.
- Historie in SeitenÄltere Kerzen werden beim Zurückscrollen zu je 500 nachgeladen, eine Anfrage nach der anderen, mit Pause nach einem Fehler.
- Kein Aufblitzen beim LadenDer Ladeschleier wartet 200 ms, daher blinkt ein schneller Symbolwechsel nie.
- Klein im DownloadDer Headless-Chart hat mit gzip 176 KB, das komplette Widget 315 KB, der WebGL-Renderer bei Bedarf weitere 18 KB.
- Tafeln, die an Ort und Stelle tickenDie Kurstafel bo-grid fasst Ticks zu einer Änderung pro Bild zusammen und zeichnet nur die geänderten Zellen neu.