Skip to content

Commit 89cc161

Browse files
committed
ImTools: split and optimize AppendTo (using Array.Resize) for the Match
1 parent 5582e2b commit 89cc161

File tree

1 file changed

+31
-3
lines changed

1 file changed

+31
-3
lines changed

src/DryIoc/ImTools.cs

+31-3
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,29 @@ private static R[] AppendTo<T, R>(T[] source, int sourcePos, int count, Func<T,
577577
return appendedResults;
578578
}
579579

580+
private static R[] Copy<T, R>(this T[] source, int sourcePos, int count, Func<T, R> map)
581+
{
582+
var results = new R[count];
583+
if (count == 1)
584+
results[0] = map(source[sourcePos]);
585+
else
586+
for (int i = 0, j = sourcePos; i < count; ++i, ++j)
587+
results[i] = map(source[j]);
588+
return results;
589+
}
590+
591+
private static R[] AppendTo<T, R>(this T[] source, R[] results, int sourcePos, int count, Func<T, R> map)
592+
{
593+
var oldResultsCount = results.Length;
594+
Array.Resize(ref results, oldResultsCount + count);
595+
if (count == 1)
596+
results[oldResultsCount] = map(source[sourcePos]);
597+
else
598+
for (int i = oldResultsCount, j = sourcePos; i < results.Length; ++i, ++j)
599+
results[i] = map(source[j]);
600+
return results;
601+
}
602+
580603
private static R[] AppendTo<S, T, R>(T[] source, S state, int sourcePos, int count, Func<S, T, R> map, R[] results = null)
581604
{
582605
if (results == null || results.Length == 0)
@@ -813,21 +836,26 @@ public static R[] Match<T, R>(this T[] source, Func<T, bool> condition, Func<T,
813836
R[] matches = null;
814837
var matchFound = false;
815838

839+
// todo: @perf optimize it for the two dissipate slices case to allocate the result matches once, keep the track of startA, endA, startB, endB of the matches.
816840
var i = 0;
817841
for (; i < source.Length; ++i)
818842
if (!(matchFound = condition(source[i])))
819843
{
820844
// for accumulated matched items
821845
if (i != 0 && i > matchStart)
822-
matches = AppendTo(source, matchStart, i - matchStart, map, matches);
846+
matches = matches == null
847+
? source.Copy(matchStart, i - matchStart, map)
848+
: source.AppendTo(matches, matchStart, i - matchStart, map);
823849
matchStart = i + 1; // guess the next match start will be after the non-matched item
824850
}
825851

826852
// when last match was found but not all items are matched (hence matchStart != 0)
827853
if (matchFound && matchStart != 0)
828-
return AppendTo(source, matchStart, i - matchStart, map, matches);
854+
return matches == null
855+
? source.Copy(matchStart, i - matchStart, map)
856+
: source.AppendTo(matches, matchStart, i - matchStart, map);
829857

830-
return matches ?? (matchStart == 0 ? AppendTo(source, 0, source.Length, map) : Empty<R>());
858+
return matches ?? (matchStart == 0 ? source.Copy(0, source.Length, map) : Empty<R>());
831859
}
832860

833861
/// <summary>Match with the additional state to use in <paramref name="condition"/> and <paramref name="map"/>

0 commit comments

Comments
 (0)