From 2d7564f4a6f4ec5491876eff9a4ae9cac11d42e9 Mon Sep 17 00:00:00 2001 From: SebastianDirks <68428517+SebastianDirks@users.noreply.github.com> Date: Tue, 19 Dec 2023 02:06:19 +0100 Subject: [PATCH] CSharp Performance: when reusing clipper objects, currently clipper sets the internal lists capacity, even if the capacity already sufficient. This causes C# to drop the currently allocated array and create a new, smaller one. (#750) This changes check if the capacity is sufficient before setting it to reduces allocations. --- CSharp/Clipper2Lib/Clipper.Engine.cs | 23 +++++++++++++++-------- CSharp/Clipper2Lib/Clipper.Offset.cs | 6 +++--- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/CSharp/Clipper2Lib/Clipper.Engine.cs b/CSharp/Clipper2Lib/Clipper.Engine.cs index bcc8ca57..1d9eb384 100644 --- a/CSharp/Clipper2Lib/Clipper.Engine.cs +++ b/CSharp/Clipper2Lib/Clipper.Engine.cs @@ -242,12 +242,19 @@ internal static void AddLocMin(Vertex vert, PathType polytype, bool isOpen, minimaList.Add(lm); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void EnsureCapacity(this List list, int minCapacity) + { + if(list.Capacity < minCapacity) + list.Capacity = minCapacity; + } + internal static void AddPathsToVertexList(Paths64 paths, PathType polytype, bool isOpen, List minimaList, List vertexList) { int totalVertCnt = 0; foreach (Path64 path in paths) totalVertCnt += path.Count; - vertexList.Capacity = vertexList.Count + totalVertCnt; + vertexList.EnsureCapacity(vertexList.Count + totalVertCnt); foreach (Path64 path in paths) { @@ -800,7 +807,7 @@ protected void Reset() _isSortedMinimaList = true; } - _scanlineList.Capacity = _minimaList.Count; + _scanlineList.EnsureCapacity(_minimaList.Count); for (int i = _minimaList.Count - 1; i >= 0; i--) _scanlineList.Add(_minimaList[i].vertex.pt.Y); @@ -2982,8 +2989,8 @@ protected bool BuildPaths(Paths64 solutionClosed, Paths64 solutionOpen) { solutionClosed.Clear(); solutionOpen.Clear(); - solutionClosed.Capacity = _outrecList.Count; - solutionOpen.Capacity = _outrecList.Count; + solutionClosed.EnsureCapacity(_outrecList.Count); + solutionOpen.EnsureCapacity(_outrecList.Count); int i = 0; // _outrecList.Count is not static here because @@ -3089,7 +3096,7 @@ protected void BuildTree(PolyPathBase polytree, Paths64 solutionOpen) polytree.Clear(); solutionOpen.Clear(); if (_hasOpenPaths) - solutionOpen.Capacity = _outrecList.Count; + solutionOpen.EnsureCapacity(_outrecList.Count); int i = 0; // _outrecList.Count is not static here because @@ -3354,10 +3361,10 @@ public bool Execute(ClipType clipType, FillRule fillRule, ClearSolutionOnly(); if (!success) return false; - solutionClosed.Capacity = solClosed64.Count; + solutionClosed.EnsureCapacity(solClosed64.Count); foreach (Path64 path in solClosed64) solutionClosed.Add(Clipper.ScalePathD(path, _invScale)); - solutionOpen.Capacity = solOpen64.Count; + solutionOpen.EnsureCapacity(solOpen64.Count); foreach (Path64 path in solOpen64) solutionOpen.Add(Clipper.ScalePathD(path, _invScale)); @@ -3394,7 +3401,7 @@ public bool Execute(ClipType clipType, FillRule fillRule, PolyTreeD polytree, Pa if (!success) return false; if (oPaths.Count > 0) { - openPaths.Capacity = oPaths.Count; + openPaths.EnsureCapacity(oPaths.Count); foreach (Path64 path in oPaths) openPaths.Add(Clipper.ScalePathD(path, _invScale)); } diff --git a/CSharp/Clipper2Lib/Clipper.Offset.cs b/CSharp/Clipper2Lib/Clipper.Offset.cs index 6c95210d..67a6121d 100644 --- a/CSharp/Clipper2Lib/Clipper.Offset.cs +++ b/CSharp/Clipper2Lib/Clipper.Offset.cs @@ -162,7 +162,7 @@ private void ExecuteInternal(double delta) { _solution.Clear(); if (_groupList.Count == 0) return; - _solution.Capacity = CalcSolutionCapacity(); + _solution.EnsureCapacity(CalcSolutionCapacity()); // make sure the offset delta is significant if (Math.Abs(delta) < 0.5) @@ -257,7 +257,7 @@ public void Execute(DeltaCallback64 deltaCallback, Paths64 solution) internal static void GetMultiBounds(Paths64 paths, List boundsList) { - boundsList.Capacity = paths.Count; + boundsList.EnsureCapacity(paths.Count); foreach (Path64 path in paths) { if (path.Count < 1) @@ -545,7 +545,7 @@ private void BuildNormals(Path64 path) { int cnt = path.Count; _normals.Clear(); - _normals.Capacity = cnt; + _normals.EnsureCapacity(cnt); for (int i = 0; i < cnt - 1; i++) _normals.Add(GetUnitNormal(path[i], path[i + 1]));