Implementing Situation Displays (part 1)

Introduction
The situation display, also called "radar display" or "radar screen" is a large display, located at the centre of the air traffic controller's working position (CWP). The information shown on a situation display includes realtime information such as aircraft positions (radar tracks) determined from primary and secondary radars, as well as static information such as sector boundaries, airways, waypoints, navaids and much more. As you can imagine, the situation display is an essential tool for enabling area controllers resolve conflicts and vectoring.
Typically, situation displays are designed using a client-server architecture, where the client handles all the rendering aspects of the flight data outlined above, and the server aggregates data originating from other systems such as flight data processing systems (FDPS) and surveillance data processing systems (SDPS). The server uses the previous sources to generate a single radar track, which is displayed to the air traffic controller. The data originating from the SDPS is submitted to the server every 4 seconds. Once processed by the server, is dispatched in realtime to all display clients.
This post is part of a series describing situation display implementations. We focus here on web technologies. Before diving immmediately in, let us quickly review how situation display client and servers are usually implemented next.
Legacy Implementations
Traditionnaly, for performance reasons, the situation display client and server software are written in C++ (or any other systems programming language capable of generating native, high-performance code). However, C++ is also an "unsafe" language with few guardrails against memory-related programming errors. Unfortunately, memory bugs can threaten a system's security and stability over time.
To reflect the increasing importance of memory safety in software design, governing bodies and software providers are pushing the adoption of memory-safe programming languages such as Java, C#, Go, Python and Rust. Due to the ATM domain's safety-critical nature, adopting memory-safe languages should also be the norm.
Rust, a relatively new language in the systems programming arena, is becoming a strong challenger to C++ because it provides both the performance and memory-safety guarantees required for building safe systems software. However, native apps written in Rust are not the only viable option for building ATM solutions: the browser as an application platform is also gaining traction.
Using Web Technologies
Browser-based applications, written in JavaScript or TypeScript are gaining some traction over native applications for the following reasons:
- The availability of a large pool of developers familiar with web technologies
- Simplified deployments over HTTP
- Readily-available GUI libraries such as React, Svelte, and Leaflet for creating feature-rich single-page apps.
However, to create high-performance, data-intensive web apps, you still need to have a good grasp of the browser's runtime architecture and understand the implications of JavaScript's single thread model. Let's start by discussing the browser runtime architecture next.
The Browser Runtime
Optimizing Memory Management
The JavaScript engine does not provide determistic memory management. By "deterministic", we mean that the developer controls exactly when memory is allocated or deallocated. Unlike C/C++, where memory is manually managed, JavaScript and TypeScript rely on a garbage collector to reclaim unused memory periodically (in a similar way to Java). Developers have no control on when the garbage collector will be triggered and whenever a garbage collection cycle is initiated, the main application thread is paused in order to let the garbage collector safely reclaim memory (this is the so-called "stop the world" event). In practice, garbage collection cycles will have minimal effect on the app's performance as perceived by the user. However in apps with high refresh rates, such as game engines, frame drops may occur during garbage collection cycles.
Minimizing Dependencies
By using the browser as an application platform, you inherit an entire ecosystem of Browser APIs, even those you have no use for when building situation displays. There is little you can do about it and this is one of the disadvantages of browser platforms over native applications where you have a much finer-gained control over what is included in your software.
Optimizing Rendering
As hinted above, JavaScript and TypeScript applications are executed by the JavaScript engine in the main thread. The JavaScript engine also uses the main thread to run a centralized event loop for processing events, handling application callbacks, and rendering the UI. As a developer you cannot create additional threads because there is no concept of "multi-threading" in JavaScript. Therefore, when a long-running callback or function is being executed by the main thread, all other event handling and UI updates are effectively stalled until the callback completes, resulting in an unresponsive page. In other words, long-running tasks such as heavy data processing in callbacks can seriously degrade your app's performance and UI rendering, which would be unacceptable for a situation display.
To mitigate the effects of long-running callbacks, developers must use the Web Workers API to run intensive processing tasks in the background. A web worker thread can perform those long-running tasks independently from the main thread, without interfering with the JavaScript engine's main thread processing. When a web worker has completed its job, it can pass the results back to the main thread using messages.
Using Accelerated Graphics
Operating System Integration
A single-page browser app runs by default in a sandbox for security reasons. Therefore, a web-based CWP situation display will have limited access to the underlying operating system services outside that sandbox (such as being able to access directly the host system's filesystem). In practice, this means that a lot of configuration files which would normally be stored on the client, must either be persisted on the server or the browser's local storage.