The Universal Challenge: From Events to Insight

Every field that deals with streams of events over time shares a common challenge. A factory manager tracking items on a conveyor belt, a data scientist analyzing user clicks, and a network engineer monitoring packets are all trying to turn a series of discrete, often chaotic, events into meaningful insight. The tools may differ, but the fundamental problem is the same: how do we perceive the true nature of a system through the lens of the events it generates?

My own journey into this problem began with a network analysis tool, JitterTrap. I was seeing things that shouldn't exist: a prominent, slow-moving wave in my network throughput graph that my knowledge of the underlying system said couldn't be real. This "ghost" in the machine forced me to look for answers in an unexpected place: the field of Digital Signal Processing (DSP).

An aliased signal showing false low-frequency variation The "ghost" in the machine: a prominent, slow-moving wave that was an artifact of the measurement process, not a real signal in the network traffic.

This three-part series shares the lessons from that journey. Part 1 introduces the core DSP mental model as a powerful, universal framework. Part 2 lays out a theoretical framework for analysis, and Part 3 applies that framework to perform a rigorous, quantitative analysis of a real-world measurement problem.

Thinking in Dimensions

To understand the DSP lens, we must first reconsider how we represent information. A single piece of information can be a 1D point on a line (x) or an instant in time (t). Combine two, and you get a 2D representation, like a measurement's (timestamp, magnitude). This scales up. A greyscale video frame is 3D data: a grid of pixels (x, y) each with a brightness (magnitude).

The key insight is that we constantly project multi-dimensional data into a format that suits our needs. An old black-and-white TV receives a fundamentally 2D signal—a stream of (magnitude, time)—but uses predetermined timing information to project it into a 4D experience: an (x, y) position on the screen, with a given luminosity, that changes over time.

When we analyze a stream of discrete events, we are doing the same thing. We are taking a series of events, which could be modeled as (event_present, time), and projecting them into a new dimension: a rate, like "packets per second." This new dimension, this signal, is an artificial construct. And the moment we create it, we subject it to the laws of signal processing.

The Law of the Alias

The first law I had unknowingly violated was the Nyquist Theorem, which leads to a phenomenon called aliasing. In simple terms, to accurately represent a signal, you must sample it at a rate at least twice its highest frequency. If you fail to do so, that high-frequency energy doesn't just vanish. It gets "folded down" into the lower frequencies, masquerading as a slow-moving pattern that wasn't there to begin with. The ghost in my graph was the alias of a much faster, invisible pattern in the packet stream.

This immediately begs the question: how can you ever analyze a signal that has components faster than you can measure? The answer is that you must first filter out those high frequencies.

This led to the central insight: any time you aggregate discrete events into time buckets, you are already applying a filter. The very act of counting "items per minute" or "events per millisecond" is a filtering operation. You are taking a series of instantaneous events and "blurring" them into a single, averaged value for that time interval.

0 A A visualization of the boxcar function, representing a simple count over a fixed interval. (Credit: By Qef - Own work, Public Domain, https://commons.wikimedia.org/w/index.php?curid=4309823)

The Default Filter: A Leaky Boxcar

The problem is that the default filter everyone uses—a simple count over an interval, known in DSP terms as a "boxcar" filter—is not a very good one. It's convenient, but it has a poor frequency response, which looks like a sinc function. While it has deep nulls at frequencies corresponding to its interval (e.g., a 1ms filter has a null at 1 kHz), its "sidelobes" are high. The largest sidelobe is only attenuated by about -13 dB, meaning it allows roughly 22% of the signal amplitude at that frequency to "leak" through.

Gnuplot Produced by GNUPLOT 6.0 patchlevel 1 -0.4 -0.2 0 0.2 0.4 0.6 0.8 1 0 500 1000 1500 2000 2500 3000 3500 First Null (1000 Hz) First Sidelobe Peak (1430 Hz) Amplitude ≈ -0.217 sinc(x) Linear Amplitude Frequency (Hz) Amplitude Response of Jittertrap's 1ms Boxcar Filter Figure 1: The amplitude response of Jittertrap's 1ms boxcar filter, showing its effect on different frequencies.

Gnuplot Produced by GNUPLOT 6.0 patchlevel 1 -40 -35 -30 -25 -20 -15 -10 -5 0 5 -3 -2 -1 0 1 2 3 Main Lobe First Sidelobe -13.26 dB sinc_dB(x) Amplitude (dB) Frequency (normalized as f*T, where T is the interval duration) Frequency Response of a Boxcar Filter (Sinc Function) Figure 2: The same frequency response on a logarithmic dB scale. The peak of the first sidelobe at -13.26 dB corresponds to the linear amplitude of ~0.22 shown in the previous plot, representing the "leakage."

This is not a minor detail. It is the direct, mathematical explanation for the ghost in my machine. A strong, periodic component in the original signal at just the right frequency can leak through this sidelobe and appear as a coherent, low-frequency wave in the final data. This is a universal pitfall for any analysis based on simple time-windowed averages.

Conclusion to Part 1

Viewing event data through a DSP lens reveals the hidden operations we perform on our data. It shows that the simple act of counting events in time windows is a powerful, but potentially flawed, filtering process. It gives us a name for the ghosts in our graphs—aliasing—and a precise, mathematical reason for their existence in the leaky response of our default filters.

But this is just the first step. This initial insight, while powerful, rests on a simplified view of the world. Real-world signals can be chaotic and non-stationary, and our measurement tools are themselves imperfect and "jittery". To build a trustworthy instrument, we must confront these messier realities.

Before we can quantitatively analyze these imperfections in Part 3, we must first build a more formal framework. In Part 2, we will create a "Rosetta Stone" to connect the core concepts of sampling, filtering, and frequency, giving us the tools we need for the final analysis.


Continue to Part 2: A Framework for Analysis.


Introduction: The Rosetta Stone

In Part 1, we introduced the "ghost in the machine"—an aliased signal created by the very act of measuring a stream of discrete events. We established that any time-bucketed analysis is a form of filtering. But to truly understand our measurements and build a trustworthy …

Read More

Introduction: Applying the Framework

In Part 1, we introduced the DSP lens and the problem of aliasing. In Part 2, we built a detailed theoretical framework, our "Rosetta Stone," connecting the concepts of sample rates, filters, and critical frequencies.

Now, in this final part, we apply that framework to a …

Read More

My long-running project, Jittertrap, had been neglected for a long time... Mostly, because of a lack of interest.

However, I recently had need for it at my day job, and I dusted it off, wrote down a list of things I need to fix for it to be useful to …

Read More

Thanks to rapido, it's become much simpler to test Linux device drivers for real PCIe devices in VMs.

The advantages of this approach are:

  • the host is protected from memory corruption errors caused by buggy kernel drivers
  • the PCI peripheral can be physically installed in a multi-use machine, reducing hardware …
Read More

On a good day, my day job involves building networking tools in python. Too many python networking tools look like shell scripts, spawning subprocesses for basic tools like 'ping' or 'ip' - often resulting in a fragile mess due to poor, or inconsistent error handling.

I was quite excited to find …

Read More

I'll be speaking at linux.conf.au 2018 in Sydney.

Jittertrap testing infrastructure is slowly improving. The idea is to include known test data so that the front-end rendering can be verified and refactored. I expect a sprint over the holidays and some new bugs for lca. :)

Clean up of …

Read More

New hardware for BufferUpr has arrived! I'm working on adding Wifi capability into the product and with new hardware comes new challenges.

Challenge: Find a simple way to list all the network interfaces in the system, including the PCIe slot and MAC address for each.

Solution:

find /sys/devices/pci0000 …
Read More

Fedora 23 (the current release at the time of writing) ships an outdated version of SciPy that doesn't include the spectrogram function. Installing the latest Scipy was kind-of a pain, so I thought I'd record some instructions for future-me and share it with you.

These instructions install dependencies, set up …

Read More

This is the story of my first expensive lesson in Digital Signal Processing. It is about JitterTrap, the free software that powers BufferUpr.

The premise of BufferUpr is to combine commodity hardware with open source software to create a product that can measure data stream delays of 1-100 milliseconds. This …

Read More

It was the year of 2015 and people were still developing new applications in PHP... but for those who could no longer accept the idea of installing a system-wide LAMP stack, there was a new-old fassionable thing: Containers!

This is a quick howto for creating a throw-away container for messing …

Read More

Sometimes there is good reason to talk to yourself. You might be doing a sound check, for example.

Likewise, it can be useful to route IP packets between two interfaces on the same machine using an external path. One reason to do this is to test other network devices like …

Read More

I received some encouraging comments on G+ from Jesper Dangaard Brouer about my previous post on DSCP, Linux and VLAN priorities. Those comments and the work linked to (here and here) points to a few long-standing (but minor) issues with the way DSCP priorities are handled in Linux.

  1. Some DSCP …
Read More

I recently discovered a flaw in the VLAN implementation I did at work. It seemed that the normal TCP traffic had the correct VLAN priorities applied, but audio streaming UDP traffic did not.

This was due to DSCP being applied to the streaming audio and the fact that the VLAN …

Read More

This concerns the proliferation of netlink libraries and a lack of direction and documentation.

Background:

I've configured a router with netem (see Bandwidth Throttling with NetEM Network Emulation and netem example rules) to test Tieline devices under various delay and loss network conditions.

It's not really feasible for the tester …

Read More

After finally completing task 01 of the Eudyptula Challenge, I'd like to share a few things I've learned, without divulging any crucial details about the task or solution.

tl;dr Pay attention.

Patience...

Maybe it's just the timezone, but the turn-around time for a response to a submission meant that …

Read More

It's been a few years since I set up or maintained a public mail server. It took much longer than expected to get everything working again, but here we are!

acooks @ rationali.st

Let's see how long it takes before I need to tweak spam filters again.

Read More

What's this? This little bit of interweb detritus was created for a few reasons:

  1. Transparency. Employers want to know what you've done before.
  2. To learn about "the cloud". I've done plenty of sysadmin work in the past, but that was all on my own bare metal. This helps to keep …
Read More