Mining the Chaos: Explaining Concurrency Bugs via Trace Abstraction
Abstraction and mining of traces to explain concurrency bugs
The paper proposes an automated framework for explaining concurrency bugs by mining problematic event sequences from execution traces using Sequential Pattern Mining (SPM). The core method, refined via an abstraction technique to handle trace length, identifies behavioral discrepancies between passing and failing executions.
TL;DR
Debugging multithreaded software is notoriously difficult due to non-deterministic interleavings. This paper presents a generalized framework that uses Sequential Pattern Mining (SPM) to automatically find the "smoking gun" in failing traces. By introducing a novel trace abstraction technique, the authors compress massive execution logs by over 90%, making it possible to isolate complex atomicity and order violations without needing predefined bug templates.
Background: The Generality Gap
Most existing tools for concurrency bugs are "specialists." A data-race detector won't find an atomicity violation if the locks are technically correct but the logic is flawed. The authors argue for a "generalist" approach: if a specific sequence of shared memory accesses (Read/Write) appears frequently in failing executions but rarely in passing ones, that sequence is likely the cause of the bug—regardless of whether it's a race, an atomicity violation, or an ordering issue.
The Core Challenge: The Curse of Trace Length
Standard SPM algorithms choke on long sequences. A program execution can generate thousands of events, leading to a combinatorial explosion of possible patterns.
The Solution: Macro-event Abstraction
The authors solve this by grouping consecutive events from the same thread into Macros.
- Macro-events: A sequence like
[R(x), W(x), R(y)]from Thread A becomes a single macro. - Abstract Events: Macros are further grouped into equivalence classes based on the shared variables they access.
This preserves the Context Switches (where the real trouble happens) while hiding the irrelevant local noise.

Methodology: From Traces to Explanations
The workflow follows a rigorous pipeline:
- Trace Collection: Systematically explore interleavings using tools like Inspect.
- Abstraction: Compress traces using the Macro technique.
- Mining: Use a
PrefixSpan-style algorithm to find closed sequential patterns. - Filtering & Ranking:
- Relative Support: Calculate
rel_supp = Supp(Fail) / (Supp(Fail) + Supp(Pass)). A value of 1.0 means the pattern only appears in failures. - Data-Dependency Check: Ensure the pattern involves conflicting accesses across different threads (e.g., Thread A writes what Thread B just read).
- Relative Support: Calculate
Experimental Evidence
The authors tested their approach on real-world kernels from Mozilla and Apache.
Key Performance Metrics:
- Compression: Average length reduction of 91%.
- Accuracy: In almost all cases, the top-ranked pattern precisely identified the bug.
- Speed: The post-processing (filtering) was optimized to run in seconds compared to much longer durations in previous iterations.

Critical Insight: Why This Works
The physical intuition here is that concurrency bugs are essentially inter-thread data-dependency violations. By focusing on how patterns of Read and Write relate across threads through the lens of causality (counterfactual reasoning), the authors capture the "trigger" of the error. The macro-abstraction acts as a low-pass filter, removing the high-frequency local execution details to reveal the low-frequency, high-impact interactions between threads.
Limitations & Future Work
While highly effective for shared-memory bugs, the current implementation relies on offline analysis of logs. The authors acknowledge that for massive, long-running applications, online abstraction (compressing as the trace is generated) would be a necessary next step. Additionally, extending this to deadlocks and livelocks remains an open research frontier.
Conclusion
This work bridges the gap between data mining and formal verification. It treats program debugging as a pattern-matching problem, proving that with the right abstraction, even the most chaotic multithreaded "heisenbugs" leave a detectable signature.
