From 990dbcf97f00149b4b18f96e21410c29f5f75ed5 Mon Sep 17 00:00:00 2001 From: ikpil Date: Fri, 12 Jul 2024 23:55:35 +0900 Subject: [PATCH] Changed data structure of 'neis' from List to byte[] for optimized memory usage and improved access speed in `DtLayerMonotoneRegion` --- CHANGELOG.md | 2 +- src/DotRecast.Core/Numerics/RcVec.cs | 8 ++++++++ .../DtLayerMonotoneRegion.cs | 3 ++- .../DtTileCacheBuilder.cs | 20 +++++++++++-------- src/DotRecast.Recast/RcLayers.cs | 1 - src/DotRecast.Recast/RcRasterizations.cs | 4 ++-- src/DotRecast.Recast/RcRegions.cs | 6 +++--- 7 files changed, 28 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 165b6a4..92bb78a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Nothing ### Changed -- Nothing +- Changed data structure of 'neis' from List to byte[] for optimized memory usage and improved access speed in `DtLayerMonotoneRegion` ### Removed - Nothing diff --git a/src/DotRecast.Core/Numerics/RcVec.cs b/src/DotRecast.Core/Numerics/RcVec.cs index 33c473f..aa847ee 100644 --- a/src/DotRecast.Core/Numerics/RcVec.cs +++ b/src/DotRecast.Core/Numerics/RcVec.cs @@ -135,6 +135,14 @@ namespace DotRecast.Core.Numerics @out[n + 1] = @in[m + 1]; @out[n + 2] = @in[m + 2]; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Copy(Span @out, int n, Span @in, int m) + { + @out[n + 0] = @in[m + 0]; + @out[n + 1] = @in[m + 1]; + @out[n + 2] = @in[m + 2]; + } /// Returns the distance between two points. /// @param[in] v1 A point. [(x, y, z)] diff --git a/src/DotRecast.Detour.TileCache/DtLayerMonotoneRegion.cs b/src/DotRecast.Detour.TileCache/DtLayerMonotoneRegion.cs index f4b885c..375810a 100644 --- a/src/DotRecast.Detour.TileCache/DtLayerMonotoneRegion.cs +++ b/src/DotRecast.Detour.TileCache/DtLayerMonotoneRegion.cs @@ -7,7 +7,8 @@ namespace DotRecast.Detour.TileCache public const int DT_LAYER_MAX_NEIS = 16; public int area; - public List neis = new List(DT_LAYER_MAX_NEIS); + public byte[] neis = new byte[DT_LAYER_MAX_NEIS]; + public byte nneis; public byte regId; public byte areaId; }; diff --git a/src/DotRecast.Detour.TileCache/DtTileCacheBuilder.cs b/src/DotRecast.Detour.TileCache/DtTileCacheBuilder.cs index 02ec3d2..1bb5cd1 100644 --- a/src/DotRecast.Detour.TileCache/DtTileCacheBuilder.cs +++ b/src/DotRecast.Detour.TileCache/DtTileCacheBuilder.cs @@ -181,8 +181,8 @@ namespace DotRecast.Detour.TileCache byte rai = layer.regs[ymi]; if (rai != 0xff && rai != ri) { - AddUniqueLast(regs[ri].neis, rai); - AddUniqueLast(regs[rai].neis, ri); + AddUniqueLast(regs[ri].neis, ref regs[ri].nneis, rai); + AddUniqueLast(regs[rai].neis, ref regs[rai].nneis, ri); } } } @@ -197,8 +197,9 @@ namespace DotRecast.Detour.TileCache int merge = -1; int mergea = 0; - foreach (int nei in reg.neis) + for (int j = 0; j < reg.nneis; ++j) { + byte nei = reg.neis[j]; DtLayerMonotoneRegion regn = regs[nei]; if (reg.regId == regn.regId) continue; @@ -246,12 +247,13 @@ namespace DotRecast.Detour.TileCache } } - public static void AddUniqueLast(List a, byte v) + public static void AddUniqueLast(byte[] a, ref byte an, byte v) { - int n = a.Count; + int n = an; if (n > 0 && a[n - 1] == v) return; - a.Add(v); + a[an] = v; + an++; } public static bool IsConnected(DtTileCacheLayer layer, int ia, int ib, int walkableClimb) @@ -271,9 +273,11 @@ namespace DotRecast.Detour.TileCache DtLayerMonotoneRegion reg = regs[i]; if (reg.regId != oldRegId) continue; - foreach (int nei in reg.neis) + + int nnei = reg.nneis; + for (int j = 0; j < nnei ; ++j) { - if (regs[nei].regId == newRegId) + if (regs[reg.neis[j]].regId == newRegId) count++; } } diff --git a/src/DotRecast.Recast/RcLayers.cs b/src/DotRecast.Recast/RcLayers.cs index df35834..6b92f6b 100644 --- a/src/DotRecast.Recast/RcLayers.cs +++ b/src/DotRecast.Recast/RcLayers.cs @@ -32,7 +32,6 @@ namespace DotRecast.Recast const int RC_MAX_LAYERS = RcRecast.RC_NOT_CONNECTED; const int RC_MAX_NEIS = 16; - private static void AddUnique(List a, int v) { if (!a.Contains(v)) diff --git a/src/DotRecast.Recast/RcRasterizations.cs b/src/DotRecast.Recast/RcRasterizations.cs index 177d1e3..74ed12a 100644 --- a/src/DotRecast.Recast/RcRasterizations.cs +++ b/src/DotRecast.Recast/RcRasterizations.cs @@ -209,7 +209,7 @@ namespace DotRecast.Recast /// @param[out] outVerts2Count The number of resulting polygon 2 vertices /// @param[in] axisOffset THe offset along the specified axis /// @param[in] axis The separating axis - private static void DividePoly(float[] inVerts, int inVertsOffset, int inVertsCount, + private static void DividePoly(Span inVerts, int inVertsOffset, int inVertsCount, int outVerts1, out int outVerts1Count, int outVerts2, out int outVerts2Count, float axisOffset, int axis) @@ -322,7 +322,7 @@ namespace DotRecast.Recast z1 = Math.Clamp(z1, 0, h - 1); // Clip the triangle into all grid cells it touches. - float[] buf = new float[7 * 3 * 4]; + Span buf = stackalloc float[7 * 3 * 4]; int @in = 0; int inRow = 7 * 3; int p1 = inRow + 7 * 3; diff --git a/src/DotRecast.Recast/RcRegions.cs b/src/DotRecast.Recast/RcRegions.cs index 9fab149..607259e 100644 --- a/src/DotRecast.Recast/RcRegions.cs +++ b/src/DotRecast.Recast/RcRegions.cs @@ -1665,8 +1665,8 @@ namespace DotRecast.Recast ctx.StartTimer(RcTimerLabel.RC_TIMER_BUILD_REGIONS_WATERSHED); - int LOG_NB_STACKS = 3; - int NB_STACKS = 1 << LOG_NB_STACKS; + const int LOG_NB_STACKS = 3; + const int NB_STACKS = 1 << LOG_NB_STACKS; List> lvlStacks = new List>(); for (int i = 0; i < NB_STACKS; ++i) { @@ -1756,7 +1756,7 @@ namespace DotRecast.Recast ExpandRegions(expandIters * 8, 0, chf, srcReg, srcDist, stack, true); ctx.StopTimer(RcTimerLabel.RC_TIMER_BUILD_REGIONS_WATERSHED); - + ctx.StartTimer(RcTimerLabel.RC_TIMER_BUILD_REGIONS_FILTER); // Merge regions and filter out small regions.