First-class algorithmic complexity analysis for .NET β powered by Roslyn, the Master Theorem, and Akra-Bazzi.
See Big-O time and space complexity directly in your editor, backed by a rigorous five-phase analysis pipeline that extracts recurrences from C# source code and solves them symbolically.
CodeLens annotations show time complexity, space complexity, confidence scores, and explanatory tooltips β all computed from static analysis of your C# code.
- Automatic Big-O extraction from C# source via Roslyn AST/CFG analysis
- Recurrence solving using the Master Theorem, Akra-Bazzi Theorem, and characteristic polynomial method
- 150+ .NET BCL methods pre-mapped with documented complexities (List, Dictionary, LINQ, String, etc.)
- Real-time IDE integration β VS Code CodeLens hints with debounced incremental analysis
- Amortized, parallel, probabilistic, and memory complexity analysis
- Hardware calibration β micro-benchmarking with curve fitting to verify theoretical predictions
- Confidence scoring β every result carries a confidence level so you know when to trust it
- 752 passing tests across unit, integration, and theorem-specific suites
using ComplexityAnalysis.Roslyn.Analysis;
using Microsoft.CodeAnalysis.CSharp;
// Parse your code
var tree = CSharpSyntaxTree.ParseText(sourceCode);
var compilation = CSharpCompilation.Create("Analysis", new[] { tree }, references);
// Analyze
var extractor = new RoslynComplexityExtractor(compilation.GetSemanticModel(tree));
var complexity = extractor.AnalyzeMethod(methodDeclaration);
Console.WriteLine($"Complexity: {complexity.ToBigONotation()}");
// => "Complexity: O(n log n)"cd src/ComplexityAnalysis.IDE/vscode
npm install && npm run compile && npm run package
# Install the .vsix via "Extensions: Install from VSIX..."Open any C# file and complexity annotations appear above each method signature.
cd src
dotnet test
# 752 passed, 42 skippedThe system operates as a five-phase pipeline, each phase building on the previous to produce increasingly refined complexity estimates:
Source Code
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Phase A β Static Extraction β
β Roslyn AST/CFG analysis, loop bounds, call graph, β
β BCL method lookup, mutual recursion detection β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Phase B β Recurrence Solving β
β Master Theorem, Akra-Bazzi, linear recurrence β
β (characteristic polynomial), SymPy fallback β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Phase C β Refinement β
β Slack variable optimization, perturbation β
β expansion, numerical induction, confidence scoring β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Phase D β Speculative / IDE Integration β
β Incremental parsing, incomplete code tolerance, β
β stub detection, real-time CodeLens hints β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Phase E β Hardware Calibration β
β Micro-benchmarks, curve fitting, constant factor β
β estimation, hardware profiling β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
ComplexityExpression + ConfidenceScore
| Library | Purpose |
|---|---|
ComplexityAnalysis.Core |
Expression type hierarchy, recurrence types, variables, visitor pattern |
ComplexityAnalysis.Roslyn |
Roslyn-based extractors, loop analysis, call graph, BCL mappings, speculative analysis |
ComplexityAnalysis.Solver |
Theorem applicability, critical exponent solver, integral evaluator, refinement engine |
ComplexityAnalysis.Calibration |
Micro-benchmarks, curve fitting, constant factor estimation, calibration persistence |
ComplexityAnalysis.Engine |
Pipeline orchestration |
ComplexityAnalysis.IDE |
VS Code extension (TypeScript) + .NET CLI tool |
The solver implements three complementary approaches to recurrence solving. This section covers the mathematics behind each.
For standard divide-and-conquer recurrences of the form:
where a β₯ 1 subproblems of size n/b are created and f(n) is the non-recursive work. Let d = logb(a) be the critical exponent. The three cases are:
| Case | Condition | Result |
|---|---|---|
| 1 | f(n) = O(nd β Ξ΅) for some Ξ΅ > 0 | Ξ(nd) |
| 2 | f(n) = Ξ(nd Β· logk n) | Ξ(nd Β· logk+1 n) |
| 3 | f(n) = Ξ©(nd + Ξ΅) with regularity | Ξ(f(n)) |
Case 3 requires the regularity condition: a Β· f(n/b) β€ c Β· f(n) for some c < 1. The solver verifies this numerically by sampling at multiple input sizes.
Example: Merge sort's recurrence T(n) = 2T(n/2) + n falls into Case 2 with d = 1, k = 0, yielding Ξ(n log n).
The Master Theorem cannot handle recurrences with multiple recursive terms, variable a or b, or driving functions that fall between cases (e.g., nd / log n). For these, the system falls back to Akra-Bazzi.
The Akra-Bazzi theorem generalizes the Master Theorem to multi-term recurrences:
where ai > 0, 0 < bi < 1, and |hi(n)| = O(n / logΒ² n).
Solving procedure:
- Find the unique critical exponent p satisfying:
The solver uses Newton-Raphson iteration with Brent's method as a fallback, bracketing the search interval for robust convergence.
- Evaluate the integral to obtain the closed-form solution:
For common forms of g(n), the integral has a closed-form result. When g(n) = nk: if k < p the integral is O(1); if k = p it gives O(log n); if k > p it contributes O(nk β p).
Example: The recurrence T(n) = T(n/3) + T(2n/3) + n cannot be solved by the Master Theorem (two different subproblem sizes), but Akra-Bazzi yields p = 1 and the solution Ξ(n log n).
For subtract-style recurrences common in dynamic programming and backtracking:
The solver forms the characteristic polynomial xk β aβxkβ1 β β― β ak = 0 and finds its roots. The dominant root determines the asymptotic growth:
| Root type | Contribution |
|---|---|
| Distinct real root r | c Β· rn |
| Repeated root r (multiplicity m) | (cβ + cβn + β― + cmβ1nmβ1) Β· rn |
| Complex conjugates Ξ± Β± Ξ²i | rn Β· (cβ cos(nΞΈ) + cβ sin(nΞΈ)) |
For order-2 recurrences the solver uses the quadratic formula directly; for higher orders it uses companion matrix eigenvalue decomposition.
Example: The Fibonacci recurrence T(n) = T(n β 1) + T(n β 2) has characteristic equation xΒ² β x β 1 = 0, with dominant root Ο = (1 + β5)/2 β 1.618, giving Ξ(Οn).
This distinction is critical and a common source of confusion:
| Subtract (T(n β k)) | Divide (T(n/b)) | |
|---|---|---|
| Typical growth | Exponential | Polynomial |
| Solving method | Characteristic roots | Critical exponent |
| Algorithms | DP, backtracking | Merge sort, binary search |
| Example | T(n) = 2T(n β 1) β Ξ(2n) | T(n) = 2T(n/2) β Ξ(n) |
Complexity is represented using a rich expression tree hierarchy rooted at ComplexityExpression:
ComplexityExpression
βββ ConstantComplexity O(1)
βββ LinearComplexity O(n)
βββ PolynomialComplexity O(n^k)
βββ LogarithmicComplexity O(log n)
βββ PolyLogComplexity O(n^k Β· log^j n)
βββ ExponentialComplexity O(2^n)
βββ FactorialComplexity O(n!)
βββ RecurrenceComplexity T(n) = aT(n/b) + f(n)
βββ AmortizedComplexity amortized vs. worst-case
βββ ParallelComplexity work / span model
βββ ProbabilisticComplexity expected vs. worst-case
βββ MemoryComplexity stack / heap / auxiliary space
βββ BinaryOperationComplexity +, Γ, max, min
Expressions compose algebraically (addition, multiplication, max, min) and support a visitor pattern for traversal.
Complexity can be parameterized over multiple input dimensions: InputSize (n), VertexCount (V), EdgeCount (E), TreeHeight (h), StringLength, and more.
Detects and annotates amortized costs for patterns like dynamic array resizing (List<T>.Add β O(1) amortized), hash table rehashing, and union-find with path compression (O(Ξ±(n)) amortized).
Uses the work/span model to analyze Parallel.For, Parallel.ForEach, PLINQ, Task.WhenAll/Task.WhenAny, and async/await patterns, reporting both total work and critical-path span.
Tracks expected vs. worst-case complexity for randomized algorithms, with factory methods for common patterns: QuickSort-like (E[O(n log n)], W[O(nΒ²)]), hash table lookup (E[O(1)], W[O(n)]), randomized selection, skip lists, and Bloom filters.
Analyzes stack depth from recursion, heap allocations, tail-call optimization eligibility, and in-place algorithm detection.
Over 150 .NET BCL methods are pre-mapped with complexity information and confidence-level attribution:
| Collection | Key Operations |
|---|---|
List<T> |
Add O(1)*, Contains O(n), Sort O(n log n), BinarySearch O(log n) |
Dictionary<K,V> |
Add O(1), TryGetValue O(1), ContainsKey O(1)* |
HashSet<T> |
Add O(1), Contains O(1) |
SortedSet<T> |
Add O(log n), Contains O(log n) |
LINQ |
Where O(n), OrderBy O(n log n), GroupBy O(n) |
String |
Contains O(nΒ·m), IndexOf O(nΒ·m) |
* amortized
Confidence levels: Documented (MSDN), Attested (CLRS), Empirical (benchmarked), Inferred (code-derived), Heuristic (conservative estimate).
Phase E can micro-benchmark your machine to verify theoretical complexity predictions and estimate constant factors in nanoseconds:
var calibrator = new BCLCalibrator();
var results = await calibrator.RunFullCalibration(BenchmarkOptions.Standard);
// Results include:
// - Constant factor per operation (ns)
// - RΒ² goodness-of-fit scores
// - Hardware profile (CPU, memory, OS, runtime)Calibration data is persisted as JSON for reuse across sessions.
ComplexityAnalysis.sln
βββ src/
β βββ ComplexityAnalysis.Core/ # Type system, recurrences, variables
β βββ ComplexityAnalysis.Roslyn/ # Roslyn extractors, BCL mappings, speculative analysis
β βββ ComplexityAnalysis.Solver/ # Theorem solving, critical exponent, refinement
β βββ ComplexityAnalysis.Calibration/ # Micro-benchmarks, curve fitting
β βββ ComplexityAnalysis.Engine/ # Pipeline orchestration
β βββ ComplexityAnalysis.IDE/
β β βββ vscode/ # VS Code extension (TypeScript)
β β βββ Cli/ # .NET CLI tool
β βββ ComplexityAnalysis.Tests/ # 752 tests (xUnit)
βββ docs/articles/ # Technical documentation
βββ assets/
βββ vscode-codelens.png
- .NET 8.0 β target framework
- Roslyn (Microsoft.CodeAnalysis) β C# syntax and semantic analysis
- MathNet.Numerics β root finding, numerical methods
- xUnit β test framework
- TypeScript β VS Code extension
- SymPy (optional) β symbolic integral evaluation for advanced recurrences
- DocFX β API documentation generation
- Fork the repository
- Create a feature branch
- Run tests:
cd src && dotnet test - Submit a pull request
See PHASES_AND_MILESTONES.md for current implementation status, test inventory, and upcoming work.
MIT
