Skip to content

Commit 9184854

Browse files
authored
Profiler-driven performance optimization: CPU profiling, hotspot fixes, and new benchmarks (#7)
1 parent 0189f4c commit 9184854

3 files changed

Lines changed: 181 additions & 51 deletions

File tree

benchmark/CDT.Benchmarks/Benchmarks.cs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
using BenchmarkDotNet.Attributes;
66
using BenchmarkDotNet.Configs;
7+
using BenchmarkDotNet.Diagnosers;
78
using BenchmarkDotNet.Running;
89
using CDT;
910

@@ -59,6 +60,7 @@ public static (List<V2d<double>> Vertices, List<Edge> Edges) Read(string fileNam
5960
/// ~2 600 constraint edges) – the same dataset used in the C++ CDT benchmarks.
6061
/// </summary>
6162
[MemoryDiagnoser]
63+
[EventPipeProfiler(EventPipeProfile.CpuSampling)]
6264
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]
6365
[CategoriesColumn]
6466
[ShortRunJob]
@@ -127,6 +129,16 @@ public Triangulation<double> Conforming_Auto()
127129
return cdt;
128130
}
129131

132+
[Benchmark(Description = "Conforming – AsProvided")]
133+
[BenchmarkCategory("Conforming")]
134+
public Triangulation<double> Conforming_AsProvided()
135+
{
136+
var cdt = new Triangulation<double>(VertexInsertionOrder.AsProvided);
137+
cdt.InsertVertices(_vertices);
138+
cdt.ConformToEdges(_edges);
139+
return cdt;
140+
}
141+
130142
// -- Full pipeline (insert + erase outer + holes) ------------------------
131143

132144
[Benchmark(Description = "Full pipeline – Auto")]
@@ -140,6 +152,30 @@ public Triangulation<double> FullPipeline_Auto()
140152
cdt.EraseOuterTrianglesAndHoles();
141153
return cdt;
142154
}
155+
156+
// -- Finalization APIs (EraseSuperTriangle / EraseOuterTriangles) ---------
157+
158+
[Benchmark(Description = "EraseSuperTriangle – Auto")]
159+
[BenchmarkCategory("Finalization")]
160+
public Triangulation<double> EraseSuperTriangle_Auto()
161+
{
162+
var cdt = new Triangulation<double>(VertexInsertionOrder.Auto);
163+
cdt.InsertVertices(_vertices);
164+
cdt.InsertEdges(_edges);
165+
cdt.EraseSuperTriangle();
166+
return cdt;
167+
}
168+
169+
[Benchmark(Description = "EraseOuterTriangles – Auto")]
170+
[BenchmarkCategory("Finalization")]
171+
public Triangulation<double> EraseOuterTriangles_Auto()
172+
{
173+
var cdt = new Triangulation<double>(VertexInsertionOrder.Auto);
174+
cdt.InsertVertices(_vertices);
175+
cdt.InsertEdges(_edges);
176+
cdt.EraseOuterTriangles();
177+
return cdt;
178+
}
143179
}
144180

145181
// ---------------------------------------------------------------------------
@@ -151,6 +187,7 @@ public Triangulation<double> FullPipeline_Auto()
151187
/// to measure per-vertex overhead without the noise of large datasets.
152188
/// </summary>
153189
[MemoryDiagnoser]
190+
[EventPipeProfiler(EventPipeProfile.CpuSampling)]
154191
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]
155192
[CategoriesColumn]
156193
[ShortRunJob]
@@ -206,4 +243,37 @@ public Triangulation<float> FloatVsDouble_Float()
206243
cdt.InsertEdges(ef);
207244
return cdt;
208245
}
246+
247+
[Benchmark(Description = "Small – Conforming Auto")]
248+
[BenchmarkCategory("SmallConforming")]
249+
public Triangulation<double> Small_Conforming_Auto()
250+
{
251+
var cdt = new Triangulation<double>(VertexInsertionOrder.Auto);
252+
cdt.InsertVertices(_vertices);
253+
cdt.ConformToEdges(_edges);
254+
return cdt;
255+
}
256+
257+
[Benchmark(Description = "Small – EraseSuperTriangle Auto")]
258+
[BenchmarkCategory("SmallFinalization")]
259+
public Triangulation<double> Small_EraseSuperTriangle_Auto()
260+
{
261+
var cdt = new Triangulation<double>(VertexInsertionOrder.Auto);
262+
cdt.InsertVertices(_vertices);
263+
cdt.InsertEdges(_edges);
264+
cdt.EraseSuperTriangle();
265+
return cdt;
266+
}
267+
268+
[Benchmark(Description = "Small – EraseOuterTrianglesAndHoles Auto")]
269+
[BenchmarkCategory("SmallFinalization")]
270+
public Triangulation<double> Small_EraseOuterTrianglesAndHoles_Auto()
271+
{
272+
var cdt = new Triangulation<double>(VertexInsertionOrder.Auto,
273+
IntersectingConstraintEdges.TryResolve, 0.0);
274+
cdt.InsertVertices(_vertices);
275+
cdt.InsertEdges(_edges);
276+
cdt.EraseOuterTrianglesAndHoles();
277+
return cdt;
278+
}
209279
}

src/CDT.Core/KdTree.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,14 @@ public NearestTask(int node, T minX, T minY, T maxX, T maxY, SplitDir dir, T dis
5555
private T _minX, _minY, _maxX, _maxY;
5656
private bool _boxInitialized;
5757
private int _size;
58+
private readonly T _two;
5859

5960
private NearestTask[] _stack = new NearestTask[InitialStackDepth];
6061

6162
/// <summary>Initializes an empty KD-tree with no bounding box pre-set.</summary>
6263
public KdTree()
6364
{
65+
_two = T.One + T.One;
6466
_minX = T.MinValue; _minY = T.MinValue;
6567
_maxX = T.MaxValue; _maxY = T.MaxValue;
6668
_root = AddNewNode();
@@ -70,6 +72,7 @@ public KdTree()
7072
/// <summary>Initializes an empty KD-tree with a known bounding box.</summary>
7173
public KdTree(T minX, T minY, T maxX, T maxY)
7274
{
75+
_two = T.One + T.One;
7376
_minX = minX; _minY = minY; _maxX = maxX; _maxY = maxY;
7477
_root = AddNewNode();
7578
_boxInitialized = true;
@@ -226,10 +229,9 @@ private static bool IsInsideBox(T px, T py, T minX, T minY, T maxX, T maxY)
226229
=> px >= minX && px <= maxX && py >= minY && py <= maxY;
227230

228231
[MethodImpl(MethodImplOptions.AggressiveInlining)]
229-
private static T GetMid(T minX, T minY, T maxX, T maxY, SplitDir dir)
232+
private T GetMid(T minX, T minY, T maxX, T maxY, SplitDir dir)
230233
{
231-
T two = T.One + T.One;
232-
return dir == SplitDir.X ? (minX + maxX) / two : (minY + maxY) / two;
234+
return dir == SplitDir.X ? (minX + maxX) / _two : (minY + maxY) / _two;
233235
}
234236

235237
[MethodImpl(MethodImplOptions.AggressiveInlining)]

0 commit comments

Comments
 (0)