Summary
Rope.Equals compares two ropes character-by-character using IEnumerable<char> iterators, which allocates a CharEnumerator and uses virtual dispatch per character. For StringRope (the common case wrapping a plain string), this is significantly slower than using string == directly.
This is on the hot path in DecisionDagBuilder.CheckConsistentDecision, which is called O(n²) times when building the decision DAG for large string switch statements. At 10,000 switch cases, Rope.Equals accounts for ~5.8% of total CPU time.
Benchmark
Using SwitchStatementBenchmarks.BindFile (compiles a C# file with an N-case string switch and emits IL) where Before represents the current implementation and After represents an implementation that just uses string == directly for StringRope:
| SwitchCount |
Before |
After |
Speedup |
Alloc Before |
Alloc After |
Alloc Δ |
| 100 |
62 ms |
49 ms |
-21% |
2.7 MB |
2.5 MB |
-9% |
| 1,000 |
972 ms |
628 ms |
-35% |
115 MB |
90 MB |
-22% |
| 5,000 |
12.6 s |
9.9 s |
-22% |
2,488 MB |
1,975 MB |
-21% |
| 10,000 |
44.7 s |
38.8 s |
-13% |
10,261 MB |
7,765 MB |
-24% |
Fix
Override Equals and GetHashCode in StringRope to use direct string operations instead of the IEnumerable<char> base implementation.
Summary
Rope.Equalscompares two ropes character-by-character usingIEnumerable<char>iterators, which allocates aCharEnumeratorand uses virtual dispatch per character. ForStringRope(the common case wrapping a plainstring), this is significantly slower than usingstring ==directly.This is on the hot path in
DecisionDagBuilder.CheckConsistentDecision, which is called O(n²) times when building the decision DAG for large string switch statements. At 10,000 switch cases,Rope.Equalsaccounts for ~5.8% of total CPU time.Benchmark
Using
SwitchStatementBenchmarks.BindFile(compiles a C# file with an N-case string switch and emits IL) whereBeforerepresents the current implementation andAfterrepresents an implementation that just usesstring ==directly forStringRope:Fix
Override
EqualsandGetHashCodeinStringRopeto use directstringoperations instead of theIEnumerable<char>base implementation.