Doomfana: Executing WebAssembly-Compiled Doom Within Grafana Time Series Panels

The intersection of high-performance gaming engines and enterprise-grade observability platforms presents a technical paradox that seems, at first glance, entirely impossible. In March 2022, during the annual Grafana Labs company-wide hackathon, a team of software engineers sought to bridge this gap by investigating whether the Grafana visualization engine could be pushed to its absolute computational limits by running the classic game, Doom. This project, colloquered "Doomfana," was not merely a pursuit of novelty; it served as a rigorous stress test for Grafana's live streaming capabilities, specifically focusing on the performance of time series panels and the efficient handling of high-frequency data updates. The project utilized a WebAssembly (WASM) compiled version of Doom, transformed into a custom Grafana datasource, where the game's internal state—specifically pixel color data—is rendered as a massive array of active time series within a single graph visualization.

The genesis of this technical experiment was rooted in the spirit of the "Rickroll" project previously demonstrated by the Grafana community, which used Prometheus and Grafana to render the music video for Rick Astley's "Never Gonna Give You Up." Inspired by the ability to visualize almost any data stream, the engineers—Bogdan Matei, Kostas Pelelis, and Domas Lapinskas—set out to determine if the platform could handle the extreme throughput required to stream game frames. The technical challenge involved two distinct architectural paths: either executing the game engine on a server-side instance and transmitting frame data via WebSockets to the client, or leveraging WebAssembly to run the engine directly in the user's browser and fetching data through a specialized datasource. The team ultimately focused on the latter, utilizing the WebAssembly-compiled Doom engine to run within the browser environment, effectively turning a visualization tool into a game client.

The Engineering Architecture of Doomfana

The architectural implementation of Doomfana relies on a complex interplay between WebAssembly, WebSockets, and the Grafana Live streaming feature. To achieve a visual representation of the game within a standard time series panel, the engine must be capable of extracting color information from the game's rendering pipeline and exposing it as a stream of data points.

The development team evaluated two primary methodologies for data transmission. The first option involved a server-side execution model where the game runs on a central server, and the resulting frame data is pushed to clients through Web and WebSocket protocols. This approach, while potentially easier for the client, requires significant C code implementation to ensure that frames could be safely and efficiently transported to WebSocket clients without overwhelming the network buffer. The second, and ultimately utilized, approach involved running the Doom engine via WebAssembly (WASM) directly within the browser. This method shifts the computational load of the game engine to the client's CPU, allowing the Grafana datasource to act as a bridge that fetches data from the running WASM instance.

The technical complexity of this setup is evidenced by the data density achieved during the hackathon. In a reduced resolution mode of 100x160 pixels, the implementation manages 256 active time series, where each time series represents a specific color. This results in the rendering of approximately 16,000 data points at a consistent frequency of roughly 30 frames per second. Such a high density of streaming data points places immense pressure on the browser's rendering engine and the Grafana frontend, necessitating highly optimized data handling techniques to prevent UI freezing or significant latency.

Technical Requirements and Dependency Management

Building and deploying the Doomfana plugin requires a specialized development environment capable of handling both C-based compilation and modern JavaScript/TypeScript build pipelines. The process involves compiling the original Doom source code into WebAssembly and then integrating that output into a Grafana plugin structure.

The initial phase of the build process requires the installation of several critical low-level dependencies. On systems utilizing the Homebrew package manager, the following tools must be present:

  • emscripten (the toolchain used to compile C/C++ to WebAssembly)
  • automake (for managing the build scripts)
    and SDL2 (Simple DirectMedia Layer)
  • sdl2_mixer (for handling audio components)
  • sdl2_net (for networking capabilities within the engine)
  • pkg-config (for managing library paths during compilation)

Once the environment is prepared, the core game data must be integrated. A critical step in the deployment involves locating the doom1.wad file and copying it into the ./doom-wasm/src directory. It is imperative that the file remains named exactly doom1.wad to ensure the engine's internal resource pointers remain valid. Following this, the build process must be initiated using the provided shell scripts to clean any previous build artifacts and compile the new WASM binaries. The following commands are necessary to execute this build:

bash ./doom-wasm/scripts/clean.sh ./doom-wasm/scripts/build.sh

After the compilation of the engine is complete, the resulting WebAssembly modules and their associated map files must be moved to the plugin's source directory so they can be bundled with the Grafana plugin. The specific files to be moved to ./src/img include:

  • ./doom-wasm/src/doom1.wad
  • ./doom-wasm/src/websockets-doom.wasm
  • ./doom-wasm/src/websockets-doom.wasm.map

With the binary assets in place, the final stage of the build involves the standard JavaScript ecosystem. The developer must navigate to the project root and execute the dependency installation and production build commands:

bash yarn install yarn build

To finalize the installation within a running Grafana instance, the project root must be sym-linked to the Grafron's plugin directory. This is typically achieved by linking the directory to data/plugins. Once the link is established, the user must navigate the Grafana UI to create a new "Doom" datasource and, crucially, note the generated ID for configuration purposes.

Performance Optimization Strategies for Live Streaming

The development of Doomfana provided the Grafana Labs engineering team with profound insights into optimizing the performance of live streaming time series panels. When dealing with 16,000 data points per frame at 30 FPS, even minor inefficiencies in the data pipeline can lead to catastrophic performance degradation. The following optimization strategies were identified as essential for maintaining a stable frame rate and responsive UI.

The management of the data structure itself is a primary concern. The engineers discovered that the list of fields within the data frame should remain constant. Instead of adding or removing fields, which triggers expensive configuration updates within the Grafana engine, the system should only update the values within the existing fields. This stability prevents the panel from undergoing a full re-calculation of the axes and legend.

The method of data construction also plays a vital role in the computational overhead. When assembling new data frames, the team found that initializing a fixed-length array and subsequently assigning items by their specific index is significantly more performant than using the Array.push method. This reduction in memory reallocation and pointer updates is critical when performing thousands of operations per second.

Furthermore, the configuration of the Y-axis is a key lever for performance. Rather than allowing Grafana to dynamically calculate the minimum and maximum values for the Y-axis—a process that requires scanning the entire dataset for each update—developers should configure explicit min and max values. This pre-defined range eliminates the need for the engine to perform range-finding logic on every incoming data packet.

Finally, the timing of the data push and the browser's rendering capabilities must be synchronized. The team recommends pushing new frames on the window.requestAnimationFrame tick to ensure that data updates are aligned with the browser's refresh cycle, thereby preventing screen tearing and redundant rendering. For users running the application in Google Chrome, a specific hardware acceleration setting should be verified:

text Ensure "Canvas 2d out of process rasterization" is enabled in Chrome settings.

Data Visualization Specifications

The following table summarizes the technical characteristics of the Doomfana implementation during its peak performance testing.

Metric Value
Engine Architecture WebAssembly (WASM)
Rendering Mode Half Resolution (100x160)
Active Time Series Count 256 (one per color)
Total Data Points per Frame ~16,000
Target Frame Rate ~30 FPS
Data Transport Protocol Grafana Live / WebSockets
Primary Visualization Type Time Series Panel

Analysis of the Hackathon Impact

The Doomfana project represents more than a technical curiosity; it serves as a benchmark for the limits of browser-based observability. By repurposing a high-performance game engine as a data source, the engineers demonstrated that the boundaries between "real-time monitoring" and "real-time rendering" are increasingly fluid. The ability to treat pixel colors as measurable metrics allows for a unique form of visual debugging and performance auditing.

The implications of these findings extend far beyond gaming. The optimization techniques discovered—such as fixed-length array assignment and static field configuration—are directly applicable to any high-cardinality monitoring use case, such as tracking millions of IoT sensors or monitoring microservices architectures with extreme churn. The project proved that Grafana is capable of handling much higher throughputs than traditionally expected, provided that the data structures are architected with performance-first principles in mind. Ultimately, the success of the Doomfana hackathon project lies in its ability to transform a tool designed for infrastructure stability into a platform for high-frequency, high-density visual experimentation.

Sources

  1. github.com/grafana/doom-datasource
  2. grafana.com/blog/can-grafana-run-doom/
  3. grafana.com/events/grafanacon/2022/hackathon-showcase-doom-drone-tracking-and-more/

Related Posts