-
Notifications
You must be signed in to change notification settings - Fork 0
EN 06_mathematical_model
🇺🇸 English | 🇯🇵 日本語 | Introduction
To maintain the Roslyn Incremental Source Generator's performance, you must understand the complexity (allocation cost and processing time) of each operation.
This document details the worst-case complexity of the generator's architecture and the design policies that mitigate it.
The generator processes data in two primary phases:
-
PrepareData(Data extraction phase): Extracts structural data from attributes and class definitions. -
SourceWriter(Source generation phase): Synthesizes C# source code strings using the extracted data.
Assume NamedArguments specified in a target attribute.
During attribute analysis, the generator traverses each NamedArgument to extract its value.
For example, the GetNamedArgumentExpressionSyntax method in PrepareData.cs uses a manual foreach loop and direct AST node matching to eliminate LINQ allocations:
// [WHY] Avoid LINQ to eliminate array and enumerator allocations on every keystroke.
foreach (var argument in attributeSyntax.ArgumentList.Arguments)
{
if (argument.NameEquals?.Name.Identifier.ValueText == name)
{
return argument.Expression;
}
}Because this loop executes for each target configuration (
Note
The extraction phase packages results into pure value-type DTOs using readonly record struct and EquatableArray<T>. This architectural constraint minimizes memory allocations.
Assume SourceWriter—which encapsulates a thread-static StringBuilder pool—to write linearly and suppress memory reallocation. The time complexity is exactly
Tip
By using zero-allocation scopes like using var _ = writer.ClassScope(@class);, the generator maintains Garbage Collection (GC) overhead at
The Incremental Generator caches past compilation outputs and calculates only delta changes.
In GeneratorHelper.cs, the pipeline executes the following chain:
context.ExtractData(framework, version, attributeName, prepareData, id, selectMany) // O(N)
.SelectAndReportExceptions(getSourceCode, context, id) // O(K)
.AddSource(context);Assuming an incremental cache hit ratio of
| Scenario | Cache state | Total complexity |
Impact on pipeline |
|---|---|---|---|
| Routine editing (for example, method bodies) |
Hit ( |
Terminates early via Equals() comparison. Computational overhead is effectively zero. |
|
| Structural changes (for example, base classes) |
Miss ( |
Extraction and generation re-execute across all files, reaching the theoretical worst case. |
Note
Estimated real-world performance (daily editing and typing:
-
Execution latency: Virtually 0 ms (Measured
$\le 0.1 \sim 0.5 \text{ ms}$ ) - GC heap allocation: 0 bytes
-
Developer experience impact: During method-body logic edits or keystrokes, the Roslyn pipeline terminates early via value equality comparison (
Equals()). Generator CPU and memory overhead remain effectively zero, eliminating IDE lag even in large codebases.
The most severe computational load occurs when widespread architectural changes force the cache hit ratio to
Scenario:
Modifying the name, type, or attribute parameters (for example, DefaultValue) of a [DependencyProperty] defined in a widely consumed base class.
This triggers the following compiler events:
- Roslyn identifies that all files depending on the base class are structurally affected.
- The incremental cache completely invalidates (
$H=0$ ) across all$S$ target files. - For all
$S \times P$ properties, the$O(N)$ syntax analysis and$O(K)$ source generation execute synchronously.
Worst-case complexity:
Warning
In enterprise-scale solutions (where
To prevent this worst-case complexity from triggering on every keystroke, the generator enforces strict architectural rules.
Note
Specific measures to prevent performance degradation
For detailed rules regarding the prohibition of ISymbol in DTOs, strict EquatableArray<T> implementations, and allocation-free generation via SourceWriter, see 05. Code synthesis and performance.
This wiki is automatically synchronized from spec/ in the repository.
- Introduction
- 01. FAQ & Design Rationale
- 02. Foundation & Domain
- 03. Pipeline Architecture
- 04. Framework Strategies
- 05. Synthesis & Performance
- 06. Complexity Model
- 07. Test Specification
- 08. Diagnostics Reference
- 概要
- 01. 設計思想とFAQ
- 02. 基盤とドメイン
- 03. パイプライン構造
- 04. フレームワーク別生成仕様
- 05. コード生成と最適化
- 06. 計算量モデル
- 07. テスト仕様書
- 08. 診断機能リファレンス