From c7c6e53d61852a6553e90f7ee684c8e7c13b69dc Mon Sep 17 00:00:00 2001 From: wrenge Date: Wed, 13 Nov 2024 11:32:38 +0300 Subject: [PATCH 1/7] Made list in DtPathCorridor.cs readonly --- src/DotRecast.Detour.Crowd/DtPathCorridor.cs | 23 +++++++++++-------- src/DotRecast.Detour/DtPathUtils.cs | 15 +++++++----- .../Tools/RcTestNavMeshTool.cs | 2 +- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/DotRecast.Detour.Crowd/DtPathCorridor.cs b/src/DotRecast.Detour.Crowd/DtPathCorridor.cs index 37787ae..d3b04c6 100644 --- a/src/DotRecast.Detour.Crowd/DtPathCorridor.cs +++ b/src/DotRecast.Detour.Crowd/DtPathCorridor.cs @@ -33,7 +33,7 @@ namespace DotRecast.Detour.Crowd private RcVec3f m_pos; private RcVec3f m_target; - private List m_path; + private List m_path = new List(); private int m_npath; private int m_maxPath; @@ -89,7 +89,8 @@ namespace DotRecast.Detour.Crowd /// @return True if the initialization succeeded. public bool Init(int maxPath) { - m_path = new List(maxPath); + if (m_path.Capacity < maxPath) + m_path.Capacity = maxPath; m_npath = 0; m_maxPath = maxPath; return true; @@ -218,7 +219,7 @@ namespace DotRecast.Detour.Crowd { if (res.Count > 1 && t > 0.99f) { - m_npath = DtPathUtils.MergeCorridorStartShortcut(ref m_path, m_npath, m_maxPath, res, res.Count); + m_npath = DtPathUtils.MergeCorridorStartShortcut(m_path, m_npath, m_maxPath, res, res.Count); } } } @@ -250,7 +251,7 @@ namespace DotRecast.Detour.Crowd if (status.Succeeded() && res.Count > 0) { - m_npath = DtPathUtils.MergeCorridorStartShortcut(ref m_path, m_npath, m_maxPath, res, res.Count); + m_npath = DtPathUtils.MergeCorridorStartShortcut(m_path, m_npath, m_maxPath, res, res.Count); return true; } @@ -276,7 +277,7 @@ namespace DotRecast.Detour.Crowd } // Prune path - m_path = m_path.GetRange(npos, m_npath - npos); + m_path.RemoveRange(0, npos); m_npath -= npos; refs[0] = prevRef; @@ -322,7 +323,7 @@ namespace DotRecast.Detour.Crowd var status = navquery.MoveAlongSurface(m_path[0], m_pos, npos, filter, out var result, visited, out var nvisited, MAX_VISITED); if (status.Succeeded()) { - m_npath = DtPathUtils.MergeCorridorStartMoved(ref m_path, m_npath, m_maxPath, visited, nvisited); + m_npath = DtPathUtils.MergeCorridorStartMoved(m_path, m_npath, m_maxPath, visited, nvisited); // Adjust the position to stay on top of the navmesh. m_pos = result; @@ -366,7 +367,7 @@ namespace DotRecast.Detour.Crowd var status = navquery.MoveAlongSurface(m_path[^1], m_target, npos, filter, out var result, visited, out nvisited, MAX_VISITED); if (status.Succeeded()) { - m_npath = DtPathUtils.MergeCorridorEndMoved(ref m_path, m_npath, m_maxPath, visited, nvisited); + m_npath = DtPathUtils.MergeCorridorEndMoved(m_path, m_npath, m_maxPath, visited, nvisited); // TODO: should we do that? // Adjust the position to stay on top of the navmesh. @@ -394,7 +395,11 @@ namespace DotRecast.Detour.Crowd public void SetCorridor(RcVec3f target, List path) { m_target = target; - m_path = new List(path); + if(path != m_path) + { + m_path.Clear(); + m_path.AddRange(path); + } m_npath = path.Count; } @@ -444,7 +449,7 @@ namespace DotRecast.Detour.Crowd else if (n < m_npath) { // The path is partially usable. - m_path = m_path.GetRange(0, n); + m_path.RemoveRange(n, m_path.Count - n); m_npath = n; } diff --git a/src/DotRecast.Detour/DtPathUtils.cs b/src/DotRecast.Detour/DtPathUtils.cs index 24dd8a6..688f2a0 100644 --- a/src/DotRecast.Detour/DtPathUtils.cs +++ b/src/DotRecast.Detour/DtPathUtils.cs @@ -148,7 +148,7 @@ namespace DotRecast.Detour return npath; } - public static int MergeCorridorStartMoved(ref List path, int npath, int maxPath, Span visited, int nvisited) + public static int MergeCorridorStartMoved(List path, int npath, int maxPath, Span visited, int nvisited) { int furthestPath = -1; int furthestVisited = -1; @@ -191,11 +191,12 @@ namespace DotRecast.Detour result.AddRange(path.GetRange(furthestPath, npath - furthestPath)); - path = result; + path.Clear(); + path.AddRange(result); return result.Count; } - public static int MergeCorridorEndMoved(ref List path, int npath, int maxPath, Span visited, int nvisited) + public static int MergeCorridorEndMoved(List path, int npath, int maxPath, Span visited, int nvisited) { int furthestPath = -1; int furthestVisited = -1; @@ -233,11 +234,12 @@ namespace DotRecast.Detour result.Add(v); } - path = result; + path.Clear(); + path.AddRange(path); return result.Count; } - public static int MergeCorridorStartShortcut(ref List path, int npath, int maxPath, List visited, int nvisited) + public static int MergeCorridorStartShortcut(List path, int npath, int maxPath, List visited, int nvisited) { int furthestPath = -1; int furthestVisited = -1; @@ -274,7 +276,8 @@ namespace DotRecast.Detour List result = visited.GetRange(0, furthestVisited); result.AddRange(path.GetRange(furthestPath, npath - furthestPath)); - path = result; + path.Clear(); + path.AddRange(result); return result.Count; } } diff --git a/src/DotRecast.Recast.Toolset/Tools/RcTestNavMeshTool.cs b/src/DotRecast.Recast.Toolset/Tools/RcTestNavMeshTool.cs index 4199c74..256a1df 100644 --- a/src/DotRecast.Recast.Toolset/Tools/RcTestNavMeshTool.cs +++ b/src/DotRecast.Recast.Toolset/Tools/RcTestNavMeshTool.cs @@ -98,7 +98,7 @@ namespace DotRecast.Recast.Toolset.Tools iterPos = result; - pathIterPolyCount = DtPathUtils.MergeCorridorStartMoved(ref pathIterPolys, pathIterPolyCount, MAX_POLYS, visited, nvisited); + pathIterPolyCount = DtPathUtils.MergeCorridorStartMoved(pathIterPolys, pathIterPolyCount, MAX_POLYS, visited, nvisited); pathIterPolyCount = DtPathUtils.FixupShortcuts(ref pathIterPolys, pathIterPolyCount, navQuery); var status = navQuery.GetPolyHeight(pathIterPolys[0], result, out var h); From dbc92a9aef3dd25fb25b70be22b0e59897acb9f0 Mon Sep 17 00:00:00 2001 From: wrenge Date: Wed, 13 Nov 2024 11:54:10 +0300 Subject: [PATCH 2/7] RcRentedArray AsSpan --- src/DotRecast.Core/Buffers/RcRentedArray.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/DotRecast.Core/Buffers/RcRentedArray.cs b/src/DotRecast.Core/Buffers/RcRentedArray.cs index 68f12c7..e7809f6 100644 --- a/src/DotRecast.Core/Buffers/RcRentedArray.cs +++ b/src/DotRecast.Core/Buffers/RcRentedArray.cs @@ -43,6 +43,11 @@ namespace DotRecast.Core.Buffers return _array; } + public Span AsSpan() + { + return new Span(_array, 0, Length); + } + public void Dispose() { From 2c6f6a50cc9c4e41855d5c5987b6cbcc2cebef81 Mon Sep 17 00:00:00 2001 From: wrenge Date: Wed, 13 Nov 2024 12:09:29 +0300 Subject: [PATCH 3/7] CollectionExtensions.cs List.AddRange(Span) --- src/DotRecast.Core/Collections/CollectionExtensions.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/DotRecast.Core/Collections/CollectionExtensions.cs b/src/DotRecast.Core/Collections/CollectionExtensions.cs index 82f5f5c..c610899 100644 --- a/src/DotRecast.Core/Collections/CollectionExtensions.cs +++ b/src/DotRecast.Core/Collections/CollectionExtensions.cs @@ -45,5 +45,11 @@ namespace DotRecast.Core.Collections (list[k], list[n]) = (list[n], list[k]); } } + + public static void AddRange(this IList list, Span span) + { + foreach (var i in span) + list.Add(i); + } } } \ No newline at end of file From 49da3fb4544fc32b14a192bde122efb5c76d35f5 Mon Sep 17 00:00:00 2001 From: wrenge Date: Wed, 13 Nov 2024 12:09:48 +0300 Subject: [PATCH 4/7] Removed allocations from MergeCorridorStartMoved --- src/DotRecast.Detour/DtPathUtils.cs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/DotRecast.Detour/DtPathUtils.cs b/src/DotRecast.Detour/DtPathUtils.cs index 688f2a0..2d77f6e 100644 --- a/src/DotRecast.Detour/DtPathUtils.cs +++ b/src/DotRecast.Detour/DtPathUtils.cs @@ -20,7 +20,10 @@ freely, subject to the following restrictions: using System; using System.Collections.Generic; +using DotRecast.Core.Buffers; +using DotRecast.Core.Collections; using DotRecast.Core.Numerics; +using CollectionExtensions = DotRecast.Core.Collections.CollectionExtensions; namespace DotRecast.Detour { @@ -180,20 +183,20 @@ namespace DotRecast.Detour } // Concatenate paths. - + var endIndex = nvisited - 1; + var length1 = endIndex - furthestVisited; + var length2 = npath - furthestPath; + using var result = RcRentedArray.Rent(length1 + length2); // Adjust beginning of the buffer to include the visited. - List result = new List(); // Store visited - for (int i = nvisited - 1; i > furthestVisited; --i) - { - result.Add(visited[i]); - } - - result.AddRange(path.GetRange(furthestPath, npath - furthestPath)); + for (int i = 0; i < length1; ++i) + result[i] = visited[endIndex - i]; + + path.CopyTo(furthestPath, result.AsArray(), length1, length2); path.Clear(); - path.AddRange(result); - return result.Count; + CollectionExtensions.AddRange(path, result.AsSpan()); + return result.Length; } public static int MergeCorridorEndMoved(List path, int npath, int maxPath, Span visited, int nvisited) From 4dee6b20b5838ac5cce908d21009806d1e53a769 Mon Sep 17 00:00:00 2001 From: wrenge Date: Wed, 13 Nov 2024 12:48:02 +0300 Subject: [PATCH 5/7] typo fix --- src/DotRecast.Detour/DtPathUtils.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DotRecast.Detour/DtPathUtils.cs b/src/DotRecast.Detour/DtPathUtils.cs index 2d77f6e..c58c353 100644 --- a/src/DotRecast.Detour/DtPathUtils.cs +++ b/src/DotRecast.Detour/DtPathUtils.cs @@ -238,7 +238,7 @@ namespace DotRecast.Detour } path.Clear(); - path.AddRange(path); + path.AddRange(result); return result.Count; } From 05613f196f56ed591959bc69b1fbe27721638f23 Mon Sep 17 00:00:00 2001 From: wrenge Date: Wed, 13 Nov 2024 12:52:33 +0300 Subject: [PATCH 6/7] MergeCorridorStartShortcut alloc fix --- src/DotRecast.Detour/DtPathUtils.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/DotRecast.Detour/DtPathUtils.cs b/src/DotRecast.Detour/DtPathUtils.cs index c58c353..f5e9d14 100644 --- a/src/DotRecast.Detour/DtPathUtils.cs +++ b/src/DotRecast.Detour/DtPathUtils.cs @@ -276,12 +276,15 @@ namespace DotRecast.Detour // Concatenate paths. // Adjust beginning of the buffer to include the visited. - List result = visited.GetRange(0, furthestVisited); - result.AddRange(path.GetRange(furthestPath, npath - furthestPath)); + var length1 = furthestVisited; + var length2 = npath - furthestPath; + using var result = RcRentedArray.Rent(length1 + length2); + visited.CopyTo(0, result.AsArray(), 0, length1); + path.CopyTo(furthestPath, result.AsArray(), length1, length2); path.Clear(); - path.AddRange(result); - return result.Count; + CollectionExtensions.AddRange(path, result.AsSpan()); + return result.Length; } } } \ No newline at end of file From 418a39a576737373fbf463c1c2146ec8012404ee Mon Sep 17 00:00:00 2001 From: wrenge Date: Wed, 13 Nov 2024 12:57:19 +0300 Subject: [PATCH 7/7] MergeCorridorEndMoved alloc fix --- src/DotRecast.Detour/DtPathUtils.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/DotRecast.Detour/DtPathUtils.cs b/src/DotRecast.Detour/DtPathUtils.cs index f5e9d14..254b439 100644 --- a/src/DotRecast.Detour/DtPathUtils.cs +++ b/src/DotRecast.Detour/DtPathUtils.cs @@ -231,15 +231,15 @@ namespace DotRecast.Detour } // Concatenate paths. - List result = path.GetRange(0, furthestPath); - foreach (var v in visited.Slice(furthestVisited, nvisited - furthestVisited)) - { - result.Add(v); - } + var length1 = furthestPath; + var length2 = nvisited - furthestVisited; + using var result = RcRentedArray.Rent(length1 + length2); + path.CopyTo(0, result.AsArray(), 0, length1); + visited.Slice(furthestVisited, nvisited - furthestVisited).CopyTo(result.AsSpan().Slice(length1, length2)); path.Clear(); - path.AddRange(result); - return result.Count; + CollectionExtensions.AddRange(path, result.AsSpan()); + return path.Count; } public static int MergeCorridorStartShortcut(List path, int npath, int maxPath, List visited, int nvisited) @@ -284,7 +284,7 @@ namespace DotRecast.Detour path.Clear(); CollectionExtensions.AddRange(path, result.AsSpan()); - return result.Length; + return path.Count; } } } \ No newline at end of file