Skip to content

Commit 2d5bb17

Browse files
committed
significantly increase speed of random array access operations
1 parent 249c6f5 commit 2d5bb17

1 file changed

Lines changed: 44 additions & 16 deletions

File tree

NiL.JS/Core/SparseArray.cs

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public override string ToString()
2525
}
2626
}
2727

28-
private const int SegmentSize = 16384;
28+
private const int SegmentSize = 1024;
2929

3030
private static TValue _fictive;
3131

@@ -145,9 +145,13 @@ internal ref TValue TryGetInternalForWrite(uint index, out bool got)
145145

146146
if (itemIndex >= values.Length)
147147
{
148-
if (itemIndex <= values.Length + 4)
148+
if (itemIndex <= values.Length + 4 || values.Length * 4 >= SegmentSize)
149149
{
150-
Array.Resize(ref values, Math.Min(SegmentSize, Math.Max(values.Length * 2, 8)));
150+
var newSize = Math.Min(SegmentSize, Math.Max(values.Length * 2, 8));
151+
if (newSize <= itemIndex)
152+
newSize *= 2;
153+
154+
Array.Resize(ref values, newSize);
151155

152156
_values[realSegmentIndex] = values;
153157
}
@@ -220,10 +224,8 @@ private void resizeL0(int newRealSegmentsCount)
220224
Array.Resize(ref _used, _navyData.Length);
221225

222226
for (var i = _navyData.Length - 1; i >= 0 && _navyData[i] is null; i--)
223-
_navyData[i] = [];
224-
225-
for (var i = _values.Length - 1; i >= 0 && _values[i] is null; i--)
226227
{
228+
_navyData[i] = [];
227229
_values[i] = [];
228230
}
229231
}
@@ -302,7 +304,7 @@ private enum FindNearestMode { NotLess, NotMore }
302304
}
303305
}
304306
}
305-
307+
306308
if (firstTry)
307309
{
308310
firstTry = false;
@@ -395,7 +397,7 @@ private enum FindNearestMode { NotLess, NotMore }
395397
}
396398
}
397399
}
398-
400+
399401
if (firstTry)
400402
{
401403
firstTry = false;
@@ -592,19 +594,42 @@ private ref TValue getFromTree(uint index, bool forRead, out bool got, int realS
592594
else
593595
navyItem.zeroNext = ni;
594596

597+
got = true;
598+
595599
if (ni >= navy.Length)
596600
{
597601
var newSize = ni * 2;
598602

599-
Array.Resize(ref _navyData[realSegmentIndex], newSize);
600-
Array.Resize(ref _values[realSegmentIndex], newSize);
603+
if (newSize * 2 >= SegmentSize)
604+
{
605+
values = new TValue[SegmentSize];
606+
607+
navy = _navyData[realSegmentIndex];
608+
for (var n = 0; n < navy.Length; n++)
609+
{
610+
var relativeIndex = navy[n].index & (SegmentSize - 1);
611+
if (relativeIndex == 0 && n != 0)
612+
break;
613+
614+
values[relativeIndex] = _values[realSegmentIndex][n];
615+
}
616+
617+
_values[realSegmentIndex] = values;
618+
_navyData[realSegmentIndex] = [];
619+
620+
return ref values[index & (SegmentSize - 1)];
621+
}
622+
else
623+
{
624+
Array.Resize(ref navy, newSize);
625+
Array.Resize(ref values, newSize);
601626

602-
navy = _navyData[realSegmentIndex];
603-
values = _values[realSegmentIndex];
627+
_navyData[realSegmentIndex] = navy;
628+
_values[realSegmentIndex] = values;
629+
}
604630
}
605631

606632
navy[ni].index = index;
607-
got = true;
608633
return ref values[ni];
609634
}
610635

@@ -624,14 +649,17 @@ private ref TValue getFromTree(uint index, bool forRead, out bool got, int realS
624649
var oldValue = values[i];
625650

626651
navyItem.index = index;
652+
values[i] = default!;
627653

628654
if (oldIndex < _pseudoLength)
629655
this[(int)oldIndex] = oldValue!;
630656

631-
values = _values[realSegmentIndex];
632-
values[i] = default!;
633-
634657
got = true;
658+
659+
if (_navyData[realSegmentIndex].Length == 0)
660+
i = (int)(index & (SegmentSize - 1));
661+
662+
values = _values[realSegmentIndex];
635663
return ref values[i];
636664
}
637665
else

0 commit comments

Comments
 (0)