Skip to content

Commit eedac1d

Browse files
committed
Improved performance by swapping Proxy with Int32
1 parent f4927a9 commit eedac1d

File tree

3 files changed

+54
-108
lines changed

3 files changed

+54
-108
lines changed

src/box2dx/Box2D.NetStandard/Collision/BroadPhase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ public void DestroyProxy(int proxyId)
178178
// call Commit to finalize the proxy pairs (for your time step).
179179
public void MoveProxy(int proxyId, in AABB aabb, in Vector2 displacement)
180180
{
181-
bool buffer = m_tree.MoveProxy((DynamicTree.Proxy)proxyId, aabb, displacement);
181+
bool buffer = m_tree.MoveProxy(proxyId, aabb, displacement);
182182
if (buffer)
183183
{
184184
BufferMove(proxyId);

src/box2dx/Box2D.NetStandard/Collision/DynamicTree.cs

Lines changed: 36 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ Box2DX Copyright (c) 2009 Ihar Kalasouski http://code.google.com/p/box2dx
3434
using System.Threading.Tasks;
3535
using Box2D.NetStandard.Common;
3636
using Math = System.Math;
37+
using Proxy = System.Int32;
3738

3839
namespace Box2D.NetStandard.Collision
3940
{
@@ -43,57 +44,7 @@ namespace Box2D.NetStandard.Collision
4344
/// <typeparam name="T"></typeparam>
4445
internal sealed class DynamicTree
4546
{
46-
internal readonly struct Proxy : IEquatable<Proxy>, IComparable<Proxy>
47-
{
48-
private readonly int _value;
49-
50-
public static readonly Proxy Free = -1;
51-
52-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
53-
public Proxy(int v) => _value = v;
54-
55-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
56-
public bool Equals(Proxy other)
57-
=> _value == other._value;
58-
59-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
60-
public int CompareTo(Proxy other)
61-
=> _value.CompareTo(other._value);
62-
63-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
64-
public override bool Equals(object? obj)
65-
=> obj is Proxy other && Equals(other);
66-
67-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
68-
public override int GetHashCode() => _value;
69-
70-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
71-
public static implicit operator int(Proxy n) => n._value;
72-
73-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
74-
public static implicit operator Proxy(int v) => new Proxy(v);
75-
76-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
77-
public static bool operator ==(Proxy a, Proxy b) => a._value == b._value;
78-
79-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
80-
public static bool operator !=(Proxy a, Proxy b) => a._value != b._value;
81-
82-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
83-
public static bool operator >(Proxy a, Proxy b) => a._value > b._value;
84-
85-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
86-
public static bool operator <(Proxy a, Proxy b) => a._value < b._value;
87-
88-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
89-
public static bool operator >=(Proxy a, Proxy b) => a._value >= b._value;
90-
91-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
92-
public static bool operator <=(Proxy a, Proxy b) => a._value <= b._value;
93-
94-
public override string ToString()
95-
=> _value.ToString();
96-
}
47+
private const Proxy ProxyFree = -1;
9748

9849
private struct Node
9950
{
@@ -110,7 +61,7 @@ private struct Node
11061
public bool IsLeaf
11162
{
11263
[MethodImpl(MethodImplOptions.AggressiveInlining)]
113-
get => Child2 == Proxy.Free;
64+
get => Child2 == ProxyFree;
11465
}
11566

11667
public bool IsFree
@@ -120,7 +71,7 @@ public bool IsFree
12071
}
12172

12273
public override string ToString()
123-
=> $@"Parent: {(Parent == Proxy.Free ? "None" : Parent.ToString())}, {
74+
=> $@"Parent: {(Parent == ProxyFree ? "None" : Parent.ToString())}, {
12475
(IsLeaf
12576
? Height == 0
12677
? $"Leaf: {UserData}"
@@ -139,7 +90,7 @@ public override string ToString()
13990
public int Height
14091
{
14192
[MethodImpl(MethodImplOptions.AggressiveInlining)]
142-
get => _root == Proxy.Free ? 0 : _nodes[_root].Height;
93+
get => _root == ProxyFree ? 0 : _nodes[_root].Height;
14394
}
14495

14596
public int NodeCount => _nodeCount;
@@ -173,7 +124,7 @@ public float AreaRatio
173124
{
174125
[MethodImpl(MethodImplOptions.NoInlining)]
175126
get {
176-
if (_root == Proxy.Free)
127+
if (_root == ProxyFree)
177128
{
178129
return 0;
179130
}
@@ -206,7 +157,7 @@ public float AreaRatio
206157

207158
public DynamicTree()
208159
{
209-
_root = Proxy.Free;
160+
_root = ProxyFree;
210161
_nodes = new Node[256];
211162

212163
// Build a linked list for the free list.
@@ -221,7 +172,7 @@ public DynamicTree()
221172

222173
ref var lastNode = ref _nodes[^1];
223174

224-
lastNode.Parent = Proxy.Free;
175+
lastNode.Parent = ProxyFree;
225176
lastNode.Height = -1;
226177
}
227178

@@ -233,7 +184,7 @@ public DynamicTree()
233184
private ref Node AllocateNode(out Proxy proxy)
234185
{
235186
// Expand the node pool as needed.
236-
if (_freeNodes == Proxy.Free)
187+
if (_freeNodes == ProxyFree)
237188
{
238189
// Separate method to aid inlining since this is a cold path.
239190
Expand();
@@ -245,9 +196,9 @@ private ref Node AllocateNode(out Proxy proxy)
245196
Assert(allocNode.IsFree);
246197
_freeNodes = allocNode.Parent;
247198
Assert(_freeNodes == -1 || _nodes[_freeNodes].IsFree);
248-
allocNode.Parent = Proxy.Free;
249-
allocNode.Child1 = Proxy.Free;
250-
allocNode.Child2 = Proxy.Free;
199+
allocNode.Parent = ProxyFree;
200+
allocNode.Child1 = ProxyFree;
201+
allocNode.Child2 = ProxyFree;
251202
allocNode.Height = 0;
252203
++_nodeCount;
253204
proxy = alloc;
@@ -283,7 +234,7 @@ void Expand()
283234
}
284235

285236
ref var lastNode = ref _nodes[l];
286-
lastNode.Parent = Proxy.Free;
237+
lastNode.Parent = ProxyFree;
287238
lastNode.Height = -1;
288239
_freeNodes = (Proxy) _nodeCount;
289240
}
@@ -299,8 +250,8 @@ private void FreeNode(Proxy proxy)
299250
node.Parent = _freeNodes;
300251
node.Height = -1;
301252
#if DEBUG_DYNAMIC_TREE
302-
node.Child1 = Proxy.Free;
303-
node.Child2 = Proxy.Free;
253+
node.Child1 = ProxyFree;
254+
node.Child2 = ProxyFree;
304255
#endif
305256
node.UserData = default;
306257
_freeNodes = proxy;
@@ -437,7 +388,7 @@ private void RemoveLeaf(Proxy leaf)
437388
{
438389
if (leaf == _root)
439390
{
440-
_root = Proxy.Free;
391+
_root = ProxyFree;
441392
return;
442393
}
443394

@@ -452,7 +403,7 @@ private void RemoveLeaf(Proxy leaf)
452403

453404
ref var siblingNode = ref _nodes[sibling];
454405

455-
if (grandParent != Proxy.Free)
406+
if (grandParent != ProxyFree)
456407
{
457408
// Destroy parent and connect sibling to grandParent.
458409
ref var grandParentNode = ref _nodes[grandParent];
@@ -474,7 +425,7 @@ private void RemoveLeaf(Proxy leaf)
474425
else
475426
{
476427
_root = sibling;
477-
siblingNode.Parent = Proxy.Free;
428+
siblingNode.Parent = ProxyFree;
478429
FreeNode(parent);
479430
}
480431

@@ -483,10 +434,10 @@ private void RemoveLeaf(Proxy leaf)
483434

484435
private void InsertLeaf(Proxy leaf)
485436
{
486-
if (_root == Proxy.Free)
437+
if (_root == ProxyFree)
487438
{
488439
_root = leaf;
489-
_nodes[_root].Parent = Proxy.Free;
440+
_nodes[_root].Parent = ProxyFree;
490441
return;
491442
}
492443

@@ -557,7 +508,7 @@ private void InsertLeaf(Proxy leaf)
557508
newParentNode.Height = 1 + siblingNode.Height;
558509

559510
ref var proxyNode = ref _nodes[leaf];
560-
if (oldParent != Proxy.Free)
511+
if (oldParent != ProxyFree)
561512
{
562513
// The sibling was not the root.
563514
ref var oldParentNode = ref _nodes[oldParent];
@@ -609,7 +560,7 @@ private static float EstimateCost(in AABB baseAabb, in Node node)
609560
[MethodImpl(MethodImplOptions.NoInlining)]
610561
private void Balance(Proxy index)
611562
{
612-
while (index != Proxy.Free)
563+
while (index != ProxyFree)
613564
{
614565
index = BalanceStep(index);
615566

@@ -618,8 +569,8 @@ private void Balance(Proxy index)
618569
var child1 = indexNode.Child1;
619570
var child2 = indexNode.Child2;
620571

621-
Assert(child1 != Proxy.Free);
622-
Assert(child2 != Proxy.Free);
572+
Assert(child1 != ProxyFree);
573+
Assert(child2 != ProxyFree);
623574

624575
ref var child1Node = ref _nodes[child1];
625576
ref var child2Node = ref _nodes[child2];
@@ -677,7 +628,7 @@ private Proxy BalanceStep(Proxy iA)
677628
c.Parent = a.Parent;
678629
a.Parent = iC;
679630

680-
if (c.Parent == Proxy.Free)
631+
if (c.Parent == ProxyFree)
681632
{
682633
_root = iC;
683634
}
@@ -741,7 +692,7 @@ private Proxy BalanceStep(Proxy iA)
741692
b.Parent = a.Parent;
742693
a.Parent = iB;
743694

744-
if (b.Parent == Proxy.Free)
695+
if (b.Parent == ProxyFree)
745696
{
746697
_root = iB;
747698
}
@@ -830,7 +781,7 @@ public void RebuildBottomUp(int free = 0)
830781
var proxy = (Proxy) i;
831782
if (node.IsLeaf)
832783
{
833-
node.Parent = Proxy.Free;
784+
node.Parent = ProxyFree;
834785
proxies[count++] = proxy;
835786
}
836787
else
@@ -878,7 +829,7 @@ public void RebuildBottomUp(int free = 0)
878829
parentNode.Child2 = child2;
879830
parentNode.Height = Math.Max(child1Node.Height, child2Node.Height) + 1;
880831
parentNode.Aabb = AABB.Combine(child1Node.Aabb, child2Node.Aabb);
881-
parentNode.Parent = Proxy.Free;
832+
parentNode.Parent = ProxyFree;
882833

883834
child1Node.Parent = parent;
884835
child2Node.Parent = parent;
@@ -913,7 +864,7 @@ public void Query(Func<int, bool> queryCallback, in AABB aabb)
913864
while (stack._count != 0)
914865
{
915866
var nodeId = stack.Pop();
916-
if (nodeId == Proxy.Free)
867+
if (nodeId == ProxyFree)
917868
{
918869
continue;
919870
}
@@ -970,7 +921,7 @@ public void RayCast(Func<RayCastInput, int, float> RayCastCallback, in RayCastIn
970921
while (stack._count != 0)
971922
{
972923
var nodeId = stack.Pop();
973-
if (nodeId == Proxy.Free)
924+
if (nodeId == ProxyFree)
974925
{
975926
continue;
976927
}
@@ -1030,7 +981,7 @@ private void Validate()
1030981

1031982
var freeCount = 0;
1032983
var freeIndex = _freeNodes;
1033-
while (freeIndex != Proxy.Free)
984+
while (freeIndex != ProxyFree)
1034985
{
1035986
Assert(0 <= freeIndex);
1036987
Assert(freeIndex < Capacity);
@@ -1046,22 +997,22 @@ private void Validate()
1046997
[Conditional("DEBUG")]
1047998
private void Validate(Proxy proxy)
1048999
{
1049-
if (proxy == Proxy.Free) return;
1000+
if (proxy == ProxyFree) return;
10501001

10511002
ref var node = ref _nodes[proxy];
10521003

10531004
if (proxy == _root)
10541005
{
1055-
Assert(node.Parent == Proxy.Free);
1006+
Assert(node.Parent == ProxyFree);
10561007
}
10571008

10581009
var child1 = node.Child1;
10591010
var child2 = node.Child2;
10601011

10611012
if (node.IsLeaf)
10621013
{
1063-
Assert(child1 == Proxy.Free);
1064-
Assert(child2 == Proxy.Free);
1014+
Assert(child1 == ProxyFree);
1015+
Assert(child2 == ProxyFree);
10651016
Assert(node.Height == 0);
10661017
return;
10671018
}
@@ -1095,7 +1046,7 @@ private void Validate(Proxy proxy)
10951046
[Conditional("DEBUG_DYNAMIC_TREE")]
10961047
private void ValidateHeight(Proxy proxy)
10971048
{
1098-
if (proxy == Proxy.Free)
1049+
if (proxy == ProxyFree)
10991050
{
11001051
return;
11011052
}

0 commit comments

Comments
 (0)