Skip to content

Commit cd556f1

Browse files
committed
Improve mappings merge
Buffer collection on stack that acts like usage map of indexes also serves as orderer. More memory efficient solution and faster approach for at least portion of queries
1 parent 36006f7 commit cd556f1

File tree

1 file changed

+46
-10
lines changed

1 file changed

+46
-10
lines changed

Orm/Xtensive.Orm/Orm/Rse/Transformation/ColumnMappingInspector.cs

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,10 @@ protected override void OnRecursionEntrance(Provider provider)
436436

437437
private static List<int> Merge(IEnumerable<int> left, IEnumerable<int> right)
438438
{
439+
if (TryMergeFast(left, right, out var result))
440+
return result;
441+
442+
// slow
439443
var hs = new HashSet<int>(left);
440444
foreach (var r in right) {
441445
_ = hs.Add(r);
@@ -445,18 +449,50 @@ private static List<int> Merge(IEnumerable<int> left, IEnumerable<int> right)
445449
return resultList;
446450
}
447451

448-
private static List<int> Merge(List<int> leftMap, IEnumerable<int> rightMap)
452+
private static bool TryMergeFast(IEnumerable<int> leftMap, IEnumerable<int> rightMap, out List<int> result)
449453
{
450-
var preReturn = leftMap.Union(rightMap).ToList(leftMap.Count * 2);
451-
preReturn.Sort();
452-
return preReturn;
453-
}
454+
Span<bool> usageMap = stackalloc bool[512];
455+
usageMap.Fill(false);
456+
var uniqueCount = 0;
457+
var biggestIndex = 0;
454458

455-
private static List<int> Merge(List<int> leftMap, IList<int> rightMap)
456-
{
457-
var preReturn = leftMap.Union(rightMap).ToList(leftMap.Count + rightMap.Count);
458-
preReturn.Sort();
459-
return preReturn;
459+
// leftMap.Concat(rightMap) is slower!
460+
foreach (var idx in leftMap) {
461+
if (idx >= usageMap.Length) {
462+
result = null;
463+
return false;
464+
}
465+
if (!usageMap[idx]) {
466+
uniqueCount++;
467+
usageMap[idx] = true;
468+
}
469+
if (biggestIndex < idx)
470+
biggestIndex = idx;
471+
}
472+
foreach (var idx in rightMap) {
473+
if (idx >= usageMap.Length) {
474+
result = null;
475+
return false;
476+
}
477+
if (!usageMap[idx]) {
478+
uniqueCount++;
479+
usageMap[idx] = true;
480+
}
481+
if (biggestIndex < idx)
482+
biggestIndex = idx;
483+
}
484+
var resultList = new List<int>(uniqueCount);
485+
for (int i = 0; i < biggestIndex + 1; i++) {
486+
if (usageMap[i])
487+
resultList.Add(i);
488+
}
489+
if (resultList.Count != uniqueCount) {
490+
//
491+
result = null;
492+
return false;
493+
}
494+
result = resultList;
495+
return true;
460496
}
461497

462498
private static List<int> MergeMappings(Provider originalLeft, List<int> leftMap, List<int> rightMap)

0 commit comments

Comments
 (0)