Skip to content

Commit 94e66ed

Browse files
committed
fix: SOH issue (#41)
fix: SOH issue step2 (#41) #41 fix: SOH issue step3 (#41) - #41 fix : SOH issue (#41) - #41 (comment) fix: SOH issue (#41) - #41 (comment) fix: SOH issue(#41) #41 (comment) array benchmark benchmark array test step2 test ss
1 parent 9777751 commit 94e66ed

File tree

5 files changed

+86
-31
lines changed

5 files changed

+86
-31
lines changed

src/DotRecast.Detour.Crowd/DtCrowd.cs

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ 3. This notice may not be removed or altered from any source distribution.
2222
using System.Collections.Generic;
2323
using System.Threading.Tasks;
2424
using DotRecast.Core;
25+
using DotRecast.Core.Buffers;
2526
using DotRecast.Core.Collections;
2627
using DotRecast.Core.Numerics;
2728

src/DotRecast.Detour.Crowd/DtObstacleAvoidanceQuery.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ 3. This notice may not be removed or altered from any source distribution.
2020

2121
using System;
2222
using DotRecast.Core;
23+
using DotRecast.Core.Buffers;
2324
using DotRecast.Core.Numerics;
2425

2526

@@ -402,7 +403,7 @@ public int SampleVelocityAdaptive(RcVec3f pos, float rad, float vmax, RcVec3f ve
402403
debug.Reset();
403404

404405
// Build sampling pattern aligned to desired velocity.
405-
float[] pat = new float[(DT_MAX_PATTERN_DIVS * DT_MAX_PATTERN_RINGS + 1) * 2];
406+
using var pat = RcRentedArray.Rent<float>((DT_MAX_PATTERN_DIVS * DT_MAX_PATTERN_RINGS + 1) * 2);
406407
int npat = 0;
407408

408409
int ndivs = m_params.adaptiveDivs;

src/DotRecast.Detour/DtNavMesh.cs

+4-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ 3. This notice may not be removed or altered from any source distribution.
2121
using System;
2222
using System.Collections.Generic;
2323
using DotRecast.Core;
24+
using DotRecast.Core.Buffers;
2425
using DotRecast.Core.Numerics;
2526

2627
namespace DotRecast.Detour
@@ -1246,14 +1247,14 @@ public bool GetPolyHeight(DtMeshTile tile, DtPoly poly, RcVec3f pos, out float h
12461247

12471248
int ip = poly.index;
12481249

1249-
float[] verts = new float[m_maxVertPerPoly * 3];
1250+
using var verts = RcRentedArray.Rent<float>(m_maxVertPerPoly * 3);
12501251
int nv = poly.vertCount;
12511252
for (int i = 0; i < nv; ++i)
12521253
{
1253-
RcArrays.Copy(tile.data.verts, poly.verts[i] * 3, verts, i * 3, 3);
1254+
RcArrays.Copy(tile.data.verts, poly.verts[i] * 3, verts.AsArray(), i * 3, 3);
12541255
}
12551256

1256-
if (!DtUtils.PointInPolygon(pos, verts, nv))
1257+
if (!DtUtils.PointInPolygon(pos, verts.AsArray(), nv))
12571258
{
12581259
return false;
12591260
}

src/DotRecast.Detour/DtNavMeshQuery.cs

+30-27
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ 3. This notice may not be removed or altered from any source distribution.
2121
using System;
2222
using System.Collections.Generic;
2323
using DotRecast.Core;
24+
using DotRecast.Core.Buffers;
2425
using DotRecast.Core.Collections;
2526
using DotRecast.Core.Numerics;
2627

@@ -41,9 +42,9 @@ public class DtNavMeshQuery
4142
public DtNavMeshQuery(DtNavMesh nav)
4243
{
4344
m_nav = nav;
44-
m_tinyNodePool = new DtNodePool();
4545
m_nodePool = new DtNodePool();
4646
m_openList = new DtNodeQueue();
47+
m_tinyNodePool = new DtNodePool();
4748
}
4849

4950
/// Returns random location on navmesh.
@@ -137,18 +138,18 @@ public DtStatus FindRandomPoint(IDtQueryFilter filter, IRcRand frand, out long r
137138
}
138139

139140
// Randomly pick point on polygon.
140-
float[] verts = new float[3 * m_nav.GetMaxVertsPerPoly()];
141-
float[] areas = new float[m_nav.GetMaxVertsPerPoly()];
142-
RcArrays.Copy(tile.data.verts, poly.verts[0] * 3, verts, 0, 3);
141+
using var verts = RcRentedArray.Rent<float>(3 * m_nav.GetMaxVertsPerPoly());
142+
using var areas = RcRentedArray.Rent<float>(m_nav.GetMaxVertsPerPoly());
143+
RcArrays.Copy(tile.data.verts, poly.verts[0] * 3, verts.AsArray(), 0, 3);
143144
for (int j = 1; j < poly.vertCount; ++j)
144145
{
145-
RcArrays.Copy(tile.data.verts, poly.verts[j] * 3, verts, j * 3, 3);
146+
RcArrays.Copy(tile.data.verts, poly.verts[j] * 3, verts.AsArray(), j * 3, 3);
146147
}
147148

148149
float s = frand.Next();
149150
float t = frand.Next();
150151

151-
var pt = DtUtils.RandomPointInConvexPoly(verts, poly.vertCount, areas, s, t);
152+
var pt = DtUtils.RandomPointInConvexPoly(verts.AsArray(), poly.vertCount, areas.AsArray(), s, t);
152153
ClosestPointOnPoly(polyRef, pt, out var closest, out var _);
153154

154155
randomRef = polyRef;
@@ -386,8 +387,8 @@ public DtStatus FindRandomPointAroundCircle(long startRef, RcVec3f centerPos, fl
386387
float s = frand.Next();
387388
float t = frand.Next();
388389

389-
float[] areas = new float[randomPolyVerts.Length / 3];
390-
RcVec3f pt = DtUtils.RandomPointInConvexPoly(randomPolyVerts, randomPolyVerts.Length / 3, areas, s, t);
390+
using var areas = RcRentedArray.Rent<float>(randomPolyVerts.Length / 3);
391+
RcVec3f pt = DtUtils.RandomPointInConvexPoly(randomPolyVerts, randomPolyVerts.Length / 3, areas.AsArray(), s, t);
391392
ClosestPointOnPoly(randomPolyRef, pt, out var closest, out var _);
392393

393394
randomRef = randomPolyRef;
@@ -457,16 +458,16 @@ public DtStatus ClosestPointOnPolyBoundary(long refs, RcVec3f pos, out RcVec3f c
457458
}
458459

459460
// Collect vertices.
460-
float[] verts = new float[m_nav.GetMaxVertsPerPoly() * 3];
461-
float[] edged = new float[m_nav.GetMaxVertsPerPoly()];
462-
float[] edget = new float[m_nav.GetMaxVertsPerPoly()];
461+
using var verts = RcRentedArray.Rent<float>(m_nav.GetMaxVertsPerPoly() * 3);
462+
using var edged = RcRentedArray.Rent<float>(m_nav.GetMaxVertsPerPoly());
463+
using var edget = RcRentedArray.Rent<float>(m_nav.GetMaxVertsPerPoly());
463464
int nv = poly.vertCount;
464465
for (int i = 0; i < nv; ++i)
465466
{
466-
RcArrays.Copy(tile.data.verts, poly.verts[i] * 3, verts, i * 3, 3);
467+
RcArrays.Copy(tile.data.verts, poly.verts[i] * 3, verts.AsArray(), i * 3, 3);
467468
}
468469

469-
if (DtUtils.DistancePtPolyEdgesSqr(pos, verts, nv, edged, edget))
470+
if (DtUtils.DistancePtPolyEdgesSqr(pos, verts.AsArray(), nv, edged.AsArray(), edget.AsArray()))
470471
{
471472
closest = pos;
472473
}
@@ -486,7 +487,7 @@ public DtStatus ClosestPointOnPolyBoundary(long refs, RcVec3f pos, out RcVec3f c
486487

487488
int va = imin * 3;
488489
int vb = ((imin + 1) % nv) * 3;
489-
closest = RcVecUtils.Lerp(verts, va, vb, edget[imin]);
490+
closest = RcVecUtils.Lerp(verts.AsArray(), va, vb, edget[imin]);
490491
}
491492

492493
return DtStatus.DT_SUCCESS;
@@ -1793,7 +1794,9 @@ public DtStatus MoveAlongSurface(long startRef, RcVec3f startPos, RcVec3f endPos
17931794
resultPos = RcVec3f.Zero;
17941795

17951796
if (null != visited)
1797+
{
17961798
visited.Clear();
1799+
}
17971800

17981801
// Validate input
17991802
if (!m_nav.IsValidPolyRef(startRef) || !startPos.IsFinite()
@@ -1822,7 +1825,7 @@ public DtStatus MoveAlongSurface(long startRef, RcVec3f startPos, RcVec3f endPos
18221825
var searchPos = RcVec3f.Lerp(startPos, endPos, 0.5f);
18231826
float searchRadSqr = RcMath.Sqr(RcVec3f.Distance(startPos, endPos) / 2.0f + 0.001f);
18241827

1825-
float[] verts = new float[m_nav.GetMaxVertsPerPoly() * 3];
1828+
using var verts = RcRentedArray.Rent<float>(m_nav.GetMaxVertsPerPoly() * 3);
18261829

18271830
const int MAX_NEIS = 8;
18281831
Span<long> neis = stackalloc long[MAX_NEIS];
@@ -1842,11 +1845,11 @@ public DtStatus MoveAlongSurface(long startRef, RcVec3f startPos, RcVec3f endPos
18421845
int nverts = curPoly.vertCount;
18431846
for (int i = 0; i < nverts; ++i)
18441847
{
1845-
RcArrays.Copy(curTile.data.verts, curPoly.verts[i] * 3, verts, i * 3, 3);
1848+
RcArrays.Copy(curTile.data.verts, curPoly.verts[i] * 3, verts.AsArray(), i * 3, 3);
18461849
}
18471850

18481851
// If target is inside the poly, stop search.
1849-
if (DtUtils.PointInPolygon(endPos, verts, nverts))
1852+
if (DtUtils.PointInPolygon(endPos, verts.AsArray(), nverts))
18501853
{
18511854
bestNode = curNode;
18521855
bestPos = endPos;
@@ -1897,11 +1900,11 @@ public DtStatus MoveAlongSurface(long startRef, RcVec3f startPos, RcVec3f endPos
18971900
// Wall edge, calc distance.
18981901
int vj = j * 3;
18991902
int vi = i * 3;
1900-
var distSqr = DtUtils.DistancePtSegSqr2D(endPos, verts, vj, vi, out var tseg);
1903+
var distSqr = DtUtils.DistancePtSegSqr2D(endPos, verts.AsArray(), vj, vi, out var tseg);
19011904
if (distSqr < bestDist)
19021905
{
19031906
// Update nearest distance.
1904-
bestPos = RcVecUtils.Lerp(verts, vj, vi, tseg);
1907+
bestPos = RcVecUtils.Lerp(verts.AsArray(), vj, vi, tseg);
19051908
bestDist = distSqr;
19061909
bestNode = curNode;
19071910
}
@@ -1921,7 +1924,7 @@ public DtStatus MoveAlongSurface(long startRef, RcVec3f startPos, RcVec3f endPos
19211924
// TODO: Maybe should use GetPortalPoints(), but this one is way faster.
19221925
int vj = j * 3;
19231926
int vi = i * 3;
1924-
var distSqr = DtUtils.DistancePtSegSqr2D(searchPos, verts, vj, vi, out var _);
1927+
var distSqr = DtUtils.DistancePtSegSqr2D(searchPos, verts.AsArray(), vj, vi, out var _);
19251928
if (distSqr > searchRadSqr)
19261929
{
19271930
continue;
@@ -2245,7 +2248,7 @@ public DtStatus Raycast(long startRef, RcVec3f startPos, RcVec3f endPos,
22452248
hit.path.Clear();
22462249
hit.pathCost = 0;
22472250

2248-
RcVec3f[] verts = new RcVec3f[m_nav.GetMaxVertsPerPoly() + 1];
2251+
using var verts = RcRentedArray.Rent<RcVec3f>(m_nav.GetMaxVertsPerPoly() + 1);
22492252

22502253
RcVec3f curPos = RcVec3f.Zero;
22512254
RcVec3f lastPos = RcVec3f.Zero;
@@ -2279,7 +2282,7 @@ public DtStatus Raycast(long startRef, RcVec3f startPos, RcVec3f endPos,
22792282
nv++;
22802283
}
22812284

2282-
bool intersects = DtUtils.IntersectSegmentPoly2D(startPos, endPos, verts, nv, out var tmin, out var tmax, out var segMin, out var segMax);
2285+
bool intersects = DtUtils.IntersectSegmentPoly2D(startPos, endPos, verts.AsArray(), nv, out var tmin, out var tmax, out var segMin, out var segMax);
22832286
if (!intersects)
22842287
{
22852288
// Could not hit the polygon, keep the old t and report hit.
@@ -2874,8 +2877,8 @@ public DtStatus FindLocalNeighbourhood(long startRef, RcVec3f centerPos, float r
28742877

28752878
float radiusSqr = RcMath.Sqr(radius);
28762879

2877-
float[] pa = new float[m_nav.GetMaxVertsPerPoly() * 3];
2878-
float[] pb = new float[m_nav.GetMaxVertsPerPoly() * 3];
2880+
using var pa = RcRentedArray.Rent<float>(m_nav.GetMaxVertsPerPoly() * 3);
2881+
using var pb = RcRentedArray.Rent<float>(m_nav.GetMaxVertsPerPoly() * 3);
28792882

28802883
while (0 < stack.Count)
28812884
{
@@ -2946,7 +2949,7 @@ public DtStatus FindLocalNeighbourhood(long startRef, RcVec3f centerPos, float r
29462949
int npa = neighbourPoly.vertCount;
29472950
for (int k = 0; k < npa; ++k)
29482951
{
2949-
RcArrays.Copy(neighbourTile.data.verts, neighbourPoly.verts[k] * 3, pa, k * 3, 3);
2952+
RcArrays.Copy(neighbourTile.data.verts, neighbourPoly.verts[k] * 3, pa.AsArray(), k * 3, 3);
29502953
}
29512954

29522955
bool overlap = false;
@@ -2977,10 +2980,10 @@ public DtStatus FindLocalNeighbourhood(long startRef, RcVec3f centerPos, float r
29772980
int npb = pastPoly.vertCount;
29782981
for (int k = 0; k < npb; ++k)
29792982
{
2980-
RcArrays.Copy(pastTile.data.verts, pastPoly.verts[k] * 3, pb, k * 3, 3);
2983+
RcArrays.Copy(pastTile.data.verts, pastPoly.verts[k] * 3, pb.AsArray(), k * 3, 3);
29812984
}
29822985

2983-
if (DtUtils.OverlapPolyPoly2D(pa, npa, pb, npb))
2986+
if (DtUtils.OverlapPolyPoly2D(pa.AsArray(), npa, pb.AsArray(), npb))
29842987
{
29852988
overlap = true;
29862989
break;

test/DotRecast.Core.Test/RcRentedArrayTest.cs

+49
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Xml;
35
using DotRecast.Core.Buffers;
6+
using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Serialization;
47
using NUnit.Framework;
58

69
namespace DotRecast.Core.Test;
@@ -56,4 +59,50 @@ public void TestRentedArray()
5659
Assert.Throws<NullReferenceException>(() => rentedArray[^1] = 0);
5760
}
5861
}
62+
63+
[Test]
64+
public void TestSame()
65+
{
66+
// not same
67+
{
68+
using var r1 = RcRentedArray.Rent<float>(1024);
69+
using var r2 = RcRentedArray.Rent<float>(1024);
70+
71+
Assert.That(r2.AsArray() != r1.AsArray(), Is.EqualTo(true));
72+
}
73+
74+
// same
75+
{
76+
// error case
77+
float[] r1Array;
78+
using (var r1 = RcRentedArray.Rent<float>(1024))
79+
{
80+
r1Array = r1.AsArray();
81+
for (int i = 0; i < r1.Length; ++i)
82+
{
83+
r1[i] = 123;
84+
}
85+
}
86+
87+
using var r2 = RcRentedArray.Rent<float>(1024);
88+
89+
Assert.That(r2.AsArray() == r1Array, Is.EqualTo(true));
90+
Assert.That(r2.AsArray().Sum(), Is.EqualTo(0));
91+
}
92+
}
93+
94+
[Test]
95+
public void TestDispose()
96+
{
97+
var r1 = RcRentedArray.Rent<float>(1024);
98+
for (int i = 0; i < r1.Length; ++i)
99+
{
100+
r1[i] = 123;
101+
}
102+
103+
Assert.That(r1.IsDisposed, Is.EqualTo(false));
104+
r1.Dispose();
105+
Assert.That(r1.IsDisposed, Is.EqualTo(true));
106+
Assert.That(r1.AsArray(), Is.Null);
107+
}
59108
}

0 commit comments

Comments
 (0)