Skip to content

Professional HFT Visualization Terminal: Data-to-Pixel < 16 ms

Development of a professional terminal for high-frequency trading data visualization. Off-Main-Thread architecture (Web Workers), Order Book rendering on OffscreenCanvas, and arbitrary precision math (BigInt + Decimal.js).

60 FPS
Stable frame rate at 5000+ updates/sec stream
-70%
Traffic reduction via binary protocol
< 16 ms
Data-to-pixel latency (in-app processing time)
Safe Math
Elimination of rounding errors in profit calculations
Gap Detection
Data integrity on packet loss

Executive Summary

This document presents the architectural validation and results of modernizing a professional trading terminal for an international crypto broker. Migration from traditional React DOM architecture to Off-Main-Thread (OMT) pattern using Canvas API, Web Workers, and Protocol Buffers.

Key Business Outcomes:

  • Performance: stable 60/144 FPS while processing 5000+ deltas/sec stream
  • Latency: Data-to-Pixel Latency < 16 ms (in-app processing time)
  • Traffic: 70% payload reduction (JSON → Protobuf) — critical for mobile networks
  • Safety: elimination of rounding errors in PnL (Decimal.js) and data integrity guarantee (Gap Detection)

Market Context: We don't trade at HFT speeds (that's FPGA and fiber optics) — we display data at such speeds. Data-to-Pixel Latency < 16 ms means our code processes data faster than one frame (16 ms @ 60 Hz). Network latency is beyond our control.

Technology Stack: TypeScript, React, Web Workers (OMT), OffscreenCanvas (Immediate Mode), Protobuf, BigInt (Matching Core) + Decimal.js (UI Formatting).


1. Problem Statement: React DOM Limits

1.1 Initial System State

The terminal was a classic React SPA using useState/useReducer to manage quote state. WebSocket connection processed JSON stream on Main Thread.

1.2 Identified Bottlenecks

Table 1. Legacy Terminal Performance Matrix

ComponentProblemUX Impact
React Virtual DOMEvery price tick triggers full tree ReconciliationFrame drops (Jank)
JSON ParsingSynchronous deserialization blocks Event LoopClick processing delay
Main ThreadAll operations in single thread (Single-Threaded)Input Lag up to 250ms
IEEE 754 Math0.1 + 0.2 ≠ 0.3 in JavaScriptPnL errors at $10k+
Text RenderingDOM Layout for each order book cell90%+ CPU on rendering

1.3 Quantitative Problem Assessment

Data stream: 5,000 updates/sec (Order Book + Trades)
React setState: ~1ms per call
Reconciliation: ~5ms per 1000 elements
DOM Paint: ~10ms per frame
 
Total: 5000 × 1ms = 5 sec/sec on setState
       → Impossible to process in real-time

Conclusion: React DOM architecture is physically incapable of processing high-frequency data streams. Fundamental rendering pipeline redesign required.


2. Architectural Decisions

2.1 Off-Main-Thread Architecture (OMT)

We applied a pattern from the GameDev industry: separation into processing and rendering threads.

WSDataRenderMain Actions
100%
Ctrl+Колесо или перетаскивание

Fig. 1. Data flow architecture. Main Thread only handles input processing and displays ready bitmaps. All heavy lifting is offloaded to Workers.

2.2 Technology Stack Rationale

2.2.1 Canvas API vs React DOM

Table 2. Rendering Approach Comparison

CriterionReact DOMCanvas API (Imperative)
Update 1000 cells~15ms (Reconciliation)~0.5ms (drawRect batch)
Memory Overhead1 DOM Node = ~1KB1 Pixel = 4 bytes (RGBA)
Layout ThrashingYes (reflow on every tick)No (pixel-perfect control)
AccessibilityBuilt-inRequires ARIA overlay
Development ComplexityLowHigh (GameDev patterns)

Rendering Technology Selection

Архитектурное решение
Canvas API (Imperative)

Pixel-perfect control without DOM reconciliation. 1000 cell update in ~0.5ms instead of ~15ms.

30× faster updates
No Layout Thrashing
GameDev patterns for HFT
Отклонённый вариант
SVG

DOM overhead at high update frequencies.

Same issues as React DOM
Reflow on every tick
Not suitable for 60 FPS

2.2.2 Protocol Buffers vs JSON

Table 3. Serialization Format Comparison

ParameterJSONProtocol BuffersImprovement
Packet size (Order Book)2.4 KB0.7 KB3.4× smaller
Parse time (1000 msg)45ms8ms5.6× faster
TypingRuntime checksCompile-time schemaSafer
Backward CompatibilityFragileBuilt-in (field numbers)

Serialization Format Selection

Архитектурное решение
Protocol Buffers

Compile-time schema with type generation. 3.4× smaller packet size, 5.6× faster parsing.

Compile-time typing
Built-in Backward Compatibility
Code generation for TypeScript
Отклонённый вариант
MessagePack

No strict schema and type generation.

Runtime type checks
Type errors = financial losses
No compile-time safety

2.2.3 Web Workers vs Single Thread

Table 4. Concurrency Model Comparison

ScenarioSingle ThreadWeb Workers
Flash Crash (50k msg/sec)UI Freeze 5+ secUI responsive
CPU Utilization100% Main ThreadDistributed across cores
Input Latency100-500ms< 16 ms
DebuggingSimpleRequires DevTools expertise

3. Performance Mechanisms

3.1 Message Conflation (Stream Compression)

At 5000 msg/sec, rendering every update is impossible — monitors only display 60 frames.

5K msg/sBufferRAF60 FPS
100%
Ctrl+Колесо или перетаскивание

Fig. 2. Conflation Pattern. 5000 incoming messages merge into 60 state snapshots, synchronized with monitor refresh rate.

Principle: Last value for each price "wins" (Latest Value Wins). Snapshot dispatch synchronized with requestAnimationFrame — no more than 60 times/sec. Data transferred via Transferable Objects for Zero-Copy transfer.

class OrderBookConflator {
  private buffer = new Map<string, PriceLevel>();
  private frameRequested = false;
 
  onMessage(update: PriceLevelUpdate) {
    this.buffer.set(update.price, update);
    if (!this.frameRequested) {
      this.frameRequested = true;
      requestAnimationFrame(() => this.flush());
    }
  }
 
  private flush() {
    const snapshot = Array.from(this.buffer.values());
    this.buffer.clear();
    this.frameRequested = false;
    renderWorker.postMessage({ type: 'SNAPSHOT', data: snapshot }, [snapshot.buffer]);
  }
}

3.2 OffscreenCanvas & Zero-Copy Transfer

Mechanism: Canvas is transferred to Render Worker via transferControlToOffscreen(). This is a Zero-Copy operation — Main Thread is completely freed for user input processing. React remains only a shell wrapper with Canvas placeholder.

3.3 Safe Financial Math (BigInt + Decimal.js)

Critical Architectural Decision: At 5000 msg/sec with 20+ fields = 100,000 operations/sec. Arbitrary precision libraries (BigNumber) create new objects in Heap on every operation, overloading Garbage Collector.

Solution: Separation of concerns:

  • BigInt (Scaled Integers) — for aggregation core (Conflation Engine). Order of magnitude faster, no memory pressure.
  • Decimal.js — only at final formatting stage for UI (60 times/sec, not 100,000).

IEEE 754 Problem: 0.1 + 0.2 !== 0.3 in JavaScript (result: 0.30000000000000004). At billion-dollar volumes, this leads to PnL errors at $10k+.

Architectural Solution:

  • BigInt (Scaled Integers) in core — price stored as BigInt with fixed scale 10^8. Operations without allocations, minimal GC load.
  • Decimal.js only for UI — precision: 20, ROUND_HALF_UP. Called 60 times/sec (frame rate), not 100k times/sec.

3.4 Circuit Breaker (Overload Protection)

During Flash Crash, stream can spike to 50,000 msg/sec. Without protection — Out of Memory. Circuit Breaker triggers when threshold exceeded (2000 messages in queue): flushes buffer, requests full snapshot from server, recovers in 1 second.

3.5 Gap Detection (Data Integrity Control)

At 5000 msg/sec, packets can be lost. If we lose one delta packet, the entire Order Book becomes invalid — prices "drift".

Mechanism: Every message contains sequence number. On gap detection:

  • Small gap (≤5 packets): micro-snapshot request for missing data only
  • Critical gap (>5 packets): full resync from server

Trader Guarantee: Terminal instantly requests missing data, blocking interface for milliseconds. Trader never sees false price.

3.6 Object Pooling (Fighting Garbage Collector)

To reduce GC load, Object Pooling pattern implemented in workers — message object reuse instead of creating new ones. Pre-allocation of 1000 objects at startup, acquire/release in hot path.

Result: Elimination of micro-freezes (Jank) from garbage collector. GC pauses reduced from 50-100ms to < 5ms.


4. Results and Metrics

4.1 Performance Comparative Analysis

Table 5. Key Metrics: Legacy vs OMT Architecture

MetricReact DOM (Legacy)Canvas + Workers (New)Improvement
FPS (5k msg/sec)10-15 (Janky)60 (Stable)4-6×
Input Latency100-250ms< 16 ms6-15×
CPU Usage95% (Main Thread)30% (Distributed)
Memory150MB (DOM nodes)45MB (Buffers)3.3×
Network5 Mbps (JSON)1.5 Mbps (Protobuf)3.3×
Parse Time45ms/1000 msg8ms/1000 msg5.6×

4.2 Data-to-Pixel Latency Breakdown

Table 6. In-App Processing Latency Decomposition (Client Processing Latency)

StageLegacyNew ArchitectureSavings
JSON Parse15ms15ms
Protobuf Decode2ms
React Reconciliation30ms30ms
Canvas Draw3ms
DOM Paint20ms20ms
Bitmap Transfer1ms
Total (Data-to-Pixel)65ms6ms59ms

Note: Network RTT excluded from table as we only control in-app processing. Data-to-Pixel < 16 ms = faster than one frame.

4.3 Business Results

  • VIP Retention: "lag" complaints reduced to zero
  • Session Duration: +25% average time in terminal
  • Trading Volume: +18% trade volume (UX correlation)
  • Mobile Traffic: $15k/month CDN savings (Protobuf compression)

5. Risks and Mitigation

Table 7. Risk Matrix

RiskProbabilityImpactMitigation
Safari without OffscreenCanvasMediumHighFallback to Main Thread Canvas
Memory Leaks in WorkersLowHighObject Pooling, profiling
Debugging complexityHighMediumStructured logging, Replay tools
Accessibility (a11y)MediumMediumARIA overlay for screen readers

6. Conclusions and Recommendations

This architectural transformation confirmed that Off-Main-Thread Architecture using OffscreenCanvas, Web Workers, and Protocol Buffers is the only path to creating a professional terminal for high-frequency trading data visualization on the Web platform.

Key Takeaways:

  1. OffscreenCanvas eliminates DOM overhead and provides pixel-perfect control
  2. Web Workers isolate heavy computations from UI thread, guaranteeing responsiveness
  3. Protocol Buffers reduce traffic and parsing time by 3-5×
  4. BigInt + Decimal.js — separation of concerns: speed in core, precision in UI
  5. Gap Detection + Object Pooling — data integrity guarantee and GC stability
  6. Conflation — mandatory pattern for high-frequency data streams

Recommendation: This architecture is applicable to any real-time applications with high update frequency: IoT monitoring, live dashboards, collaborative editors, online gaming.

Professional HFT Visualization Terminal: Data-to-Pixel < 16 ms — Softenq