Introduction: Proving Architectural Value Through Hard Numbers
From [Part 1] through [Part 5], we systematically re-engineered a 20-year-old Win32/MFC desktop trading platform to eliminate market-open UI freezes:
- Symbol Hash Sharding + Lock-Free RCU/CoW Snapshot Engine (
MarketDataEngine) - Multi-Exchange (Primary + ATS) Real-Time OrderBook Synthesis & Ingress-Order Deterministic State Projection
- Dedicated
ScreenWorker28-Field Background Pre-Formatting & 64MB Ring-BufferVirtualGrid - In-Flight Latch Message Suppression, ActiveX Redraw Batching, 60-Cell Persistent Back-Buffer Clipping & Scheduler Tuning
In this final installment, [Part 6], we present the production market-open scorecard (540-second peak window around 09:00 AM, AS-IS vs. TO-BE) measured under identical symbol sets and workspace layouts, followed by the Dual-Path Rollout Architecture that reduced deployment risk to zero.
1. Market-Open Peak Window (540 Seconds) AS-IS vs. TO-BE Scorecard
All measurements were captured during the most intense 540-second (9-minute) market open burst with the Watchlist Grid, Unified 10-Level OrderBook, 60-Symbol Multi-Quote Matrix, and Full-Market Real-Time Time & Sales Stream running simultaneously.
① Watchlist Grid (WatchlistView) — 99% Freeze Reduction & 2.94x Higher Throughput
| Key Metric (540s Cumulative) | AS-IS (Legacy Path) | TO-BE (New Engine Path) | Impact |
|---|---|---|---|
Max Single-Tick UI Stall (max_tick_ms) |
1,531 ms (1.53s freeze) |
15 ms |
99.0% reduction in max stall time (eliminated) |
Freezes Exceeding 100ms (>100ms Freeze) |
74 times |
0 times |
100% elimination of perceptible UI freezes |
Frame Drops Exceeding 33ms (>33ms) |
257 times |
0 times |
Sustained 60fps-grade responsiveness throughout |
Effective UI Event Throughput (total_events) |
25,361 ticks (47.0/s) |
74,562 ticks (138.1/s) |
+194% (2.94x) higher rendered throughput |
Average UI Time per Tick (avg_tick_ms) |
8.59 ms |
1.42 ms |
83.5% reduction in main UI thread load |
1.53 seconds—causing incoming ticks to back up and limiting effective screen updates to just 25,361 events over 540 seconds. In TO-BE, because background ScreenWorker threads pre-formatted all 28 fields and coalesced dirty symbols, the UI rendered nearly 3x more market updates (74,562 events) while never exceeding a 15ms frame time.
② Full-Market Real-Time Time & Sales Stream (TimeAndSalesView + VirtualGrid) — 514K Packets with Zero Drops
| Key Metric (540s Cumulative) | AS-IS (Legacy Grid) | TO-BE (VirtualGrid + StreamStore) |
Impact |
|---|---|---|---|
| Ingested Trade Packets | Legacy SB_ARRAY bottleneck |
514,918 packets (peak 3,100+/s) |
Full market broadcast ingested |
| Ring-Buffer Drops / Allocation Failures | - | 0 (dropped=0, failed=0) |
100% lossless ingestion (Zero-Drop) |
Max Single-Tick Ingestion Time (tick_max_ms) |
Multi-hundred ms spikes | 8 ms |
Strictly bounded within frame budget |
User Input Budget Yields (input_yields) |
Unsupported | 2,608 yields |
Instant mouse/scroll response under peak burst |
③ 60-Symbol Multi-Quote Matrix (MultiQuoteMatrix) & Unified OrderBook (OrderBookView)
- 60-Symbol Multi-Quote Matrix:
In AS-IS, 60 child windows independently parsed packets and repainted full-window bitmaps on every tick, causing per-window spikes up to94msand heavy GDI contention. In TO-BE, combining shared RCU snapshots + partial top-3-rect invalidation & persistent back-buffer clipping (ExtSelectClipRgn) onTrade-Onlyticks + coordinatorWakeLivescheduling keeps all 60 cells updating instantaneously. - Unified OrderBook:
PairingSharedOrderBookPipelinewith ActiveXput_Redraw(flexRDNone)batch guards and Static VI dirty-checking eliminated redundant COM layout calls and delivered immediate orderbook responsiveness.
2. Zero-Downtime Rollout Strategy for Massive Legacy Systems: Dual-Path Architecture
In a mission-critical financial trading platform used daily by hundreds of thousands of investors, an "All-or-Nothing" big-bang cutover carries unacceptable risk.
From Day 1 until final rollout, we enforced one non-negotiable engineering rule:
RQ_NORMAL, SB_NORMAL, legacy event handlers); maintain 100% runtime Dual-Path Branching controlled via DataManager.ini."
flowchart TD
A["Screen Init / Subscription Start"] --> B{"DataManagerConfig::ReadUseDataManager()"}
B -->|"UseDataManager = 1 (TO-BE)"| C["New Lock-Free RCU Engine Path (SUB_MODE_ENGINE)"]
B -->|"UseDataManager = 0 (AS-IS Default)"| D["Legacy Message Queue Path (SUB_MODE_LEGACY)"]
C --> E["Identical UI Controls & 100% Identical Display Consistency"]
D --> E
3 Decisive Advantages of the Dual-Path Design
- Microscopic Side-by-Side A/B Consistency Verification:
By launching two client instances side by side on the same workstation—one withUseDataManager=0(AS-IS) and the other withUseDataManager=1(TO-BE)—we could compare live market rendering tick by tick and catch even a 1-won or 1-share discrepancy under a microscope. - Phased Canary Rollout via Granular Feature Toggles:
Beneath the master switch (UseDataManager), hierarchical pilot flags (EnableOrderBookPilot,EnableSharedPipeline,EnableEtfEtnPilot,UseVirtualGrid, etc.) allowed us to expand coverage safely screen by screen and asset class by asset class. - 1-Second Zero-Downtime Emergency Fallback:
If an unexpected edge case ever surfaced in production, flipping a single INI flag to0immediately reverted the client to the battle-tested legacy path—without rebuilding binaries or deploying emergency code patches.
3. Epilogue: Engineering Lessons from Modernizing Legacy C++
When confronted with a multi-decade Win32/MFC codebase, it is tempting to say, "This architecture is too old—we need a complete rewrite from scratch." Yet in financial systems where thousands of subtle market microstructure rules and edge cases are baked into the code, a greenfield rewrite is rarely realistic.
The core engineering lessons from this journey are clear:
- Liberate the UI Thread:
Push endianness conversion, deserialization, derived price math, and comma-formatted string generation onto background shard and screen workers—so the main UI thread focuses exclusively on painting immutable, pre-formatted data at the monitor's refresh cadence. - Replace Mutexes with Immutability and RCU/CoW:
In read-dominated real-time market data workloads, atomic pointer RCU + Copy-on-Write backed by a lock-freeObjectPoolcompletely eradicates read-write lock contention. - In Asynchronous Parallelism, Monotonic Ingress Order Is Truth:
The more you shard workers for throughput, the more completion order can interleave. Storing raw per-domain images separately and projecting the final display state via monotonicingressOrderguarantees deterministic consistency without locks. - Question Every Profiler Counter Until the Very End:
Refusing to settle after the first wave of optimization—and relentlessly tracingPostMessagecounts, ActiveX COM call overhead, and frame coordinator math—allowed us to eliminate the final 1% of CPU waste and the last 1-second perceptual lag.
Thank you for reading this 6-part series to the end. We hope these production war stories serve as a practical reference for engineers battling high-throughput performance bottlenecks in large-scale C++ systems!