update sorting

This commit is contained in:
Mikhail 2026-03-16 23:18:00 +08:00
parent 01985d7ffb
commit ee65362a1b
5 changed files with 97 additions and 12 deletions

View File

@ -5,7 +5,6 @@ using DCFApixels.DragonECS.Core;
using DCFApixels.DragonECS.Core.Internal; using DCFApixels.DragonECS.Core.Internal;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
@ -644,7 +643,7 @@ namespace DCFApixels.DragonECS
if (_sortIncChunckBuffer.Length > 1) if (_sortIncChunckBuffer.Length > 1)
{ {
sortIncBuffer.AsSpan().Sort(new IncCountComparer(counts)); ArraySortUtility.Sort(sortIncBuffer.AsSpan(), new IncCountComparer(counts));
ConvertToChuncks(preSortingBuffer, sortIncBuffer, _sortIncChunckBuffer); ConvertToChuncks(preSortingBuffer, sortIncBuffer, _sortIncChunckBuffer);
} }
if (_sortIncChunckBuffer.Length > 0) if (_sortIncChunckBuffer.Length > 0)
@ -658,7 +657,7 @@ namespace DCFApixels.DragonECS
if (_sortExcChunckBuffer.Length > 1) if (_sortExcChunckBuffer.Length > 1)
{ {
sortExcBuffer.AsSpan().Sort(new ExcCountComparer(counts)); ArraySortUtility.Sort(sortExcBuffer.AsSpan(), new ExcCountComparer(counts));
ConvertToChuncks(preSortingBuffer, sortExcBuffer, _sortExcChunckBuffer); ConvertToChuncks(preSortingBuffer, sortExcBuffer, _sortExcChunckBuffer);
} }
// Выражение IncCount < (AllEntitesCount - ExcCount) мало вероятно будет истинным. // Выражение IncCount < (AllEntitesCount - ExcCount) мало вероятно будет истинным.
@ -668,7 +667,7 @@ namespace DCFApixels.DragonECS
if (_sortAnyChunckBuffer.Length > 1) if (_sortAnyChunckBuffer.Length > 1)
{ {
sortAnyBuffer.AsSpan().Sort(new ExcCountComparer(counts)); ArraySortUtility.Sort(sortAnyBuffer.AsSpan(), new ExcCountComparer(counts));
ConvertToChuncks(preSortingBuffer, sortAnyBuffer, _sortAnyChunckBuffer); ConvertToChuncks(preSortingBuffer, sortAnyBuffer, _sortAnyChunckBuffer);
} }
// Any не влияет на maxEntites если есть Inc и сложно высчитывается если нет Inc // Any не влияет на maxEntites если есть Inc и сложно высчитывается если нет Inc

View File

@ -146,8 +146,7 @@ namespace DCFApixels.DragonECS.Core.Internal
public EcsUnsafeSpan Execute(Comparison<int> comparison) public EcsUnsafeSpan Execute(Comparison<int> comparison)
{ {
Execute_Iternal(); Execute_Iternal();
Span<int> result = _filteredAllEntities.AsSpan(_filteredAllEntitiesCount); ArraySortUtility.Sort(_filteredAllEntities.AsSpan(_filteredAllEntitiesCount), comparison);
result.Sort(comparison);
return new EcsUnsafeSpan(World.ID, _filteredAllEntities.Ptr, _filteredAllEntitiesCount); return new EcsUnsafeSpan(World.ID, _filteredAllEntities.Ptr, _filteredAllEntitiesCount);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -158,8 +157,7 @@ namespace DCFApixels.DragonECS.Core.Internal
return Execute(comparison); return Execute(comparison);
} }
ExecuteFor_Iternal(source); ExecuteFor_Iternal(source);
Span<int> result = _filteredEntities.AsSpan(_filteredEntitiesCount); ArraySortUtility.Sort(_filteredEntities.AsSpan(_filteredEntitiesCount), comparison);
result.Sort(comparison);
return new EcsUnsafeSpan(World.ID, _filteredEntities.Ptr, _filteredEntitiesCount); return new EcsUnsafeSpan(World.ID, _filteredEntities.Ptr, _filteredEntitiesCount);
} }
#endregion #endregion

View File

@ -180,6 +180,11 @@ namespace DCFApixels.DragonECS.Core.Internal
{ {
return From<T>(new ReadOnlySpan<T>(ptr, length)); return From<T>(new ReadOnlySpan<T>(ptr, length));
} }
public static HMem<T> From<T>(T[] source)
where T : unmanaged
{
return From(new ReadOnlySpan<T>(source));
}
public static HMem<T> From<T>(ReadOnlySpan<T> source) public static HMem<T> From<T>(ReadOnlySpan<T> source)
where T : unmanaged where T : unmanaged
{ {

View File

@ -4,7 +4,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
#if ENABLE_IL2CPP #if ENABLE_IL2CPP
using Unity.IL2CPP.CompilerServices; using Unity.IL2CPP.CompilerServices;
@ -16,17 +15,89 @@ namespace DCFApixels.DragonECS.Core.Internal
[Il2CppSetOption(Option.NullChecks, false)] [Il2CppSetOption(Option.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)] [Il2CppSetOption(Option.ArrayBoundsChecks, false)]
#endif #endif
internal static class ArraySortUtility internal static unsafe class ArraySortUtility
{ {
internal static StructComparison<T> ToStruct<T>(this Comparison<T> self) internal static StructComparison<T> ToStruct<T>(this Comparison<T> self)
{ {
return new StructComparison<T>(self); return new StructComparison<T>(self);
} }
internal static StructComparer<T> ToStruct<T>(this Comparer<T> self)
{
return new StructComparer<T>(self);
}
public static void Sort<T>(Span<T> span)
{
var c = Comparer<T>.Default.ToStruct();
ArraySortUtility<T, StructComparer<T>>.Sort(span, ref c);
}
public static void Sort<T>(Span<T> span, Comparer<T> comparer)
{
var c = comparer.ToStruct();
ArraySortUtility<T, StructComparer<T>>.Sort(span, ref c);
}
public static void Sort<T>(Span<T> span, Comparison<T> comparison) public static void Sort<T>(Span<T> span, Comparison<T> comparison)
{ {
var c = comparison.ToStruct(); var c = comparison.ToStruct();
ArraySortUtility<T, StructComparison<T>>.Sort(span, ref c); ArraySortUtility<T, StructComparison<T>>.Sort(span, ref c);
} }
public static void Sort<T, TComparer>(Span<T> span, ref TComparer comparer)
where TComparer : struct, IComparer<T>
{
ArraySortUtility<T, TComparer>.Sort(span, ref comparer);
}
public static void Sort<T, TComparer>(Span<T> span, TComparer comparer)
where TComparer : struct, IComparer<T>
{
ArraySortUtility<T, TComparer>.Sort(span, ref comparer);
}
// Таблица для De Bruijn-умножения (позиция старшего бита для чисел 0..31)
private const int Log2DeBruijn32_Length = 32;
private static readonly uint* Log2DeBruijn32 = MemoryAllocator.From(new uint[Log2DeBruijn32_Length]
{
0, 9, 1, 10, 13, 21, 2, 29, 11, 14,
16, 18, 22, 25, 3, 30, 8, 12, 20, 28,
15, 17, 24, 7, 19, 27, 23, 6, 26, 5,
4, 31
//0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
//8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
}).Ptr;
/// <summary>32-битный логарифм по основанию 2 (округление вниз). Для value = 0 возвращает 0.</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Log2(uint value)
{
// Для нуля сразу возвращаем 0 (по договорённости, чтобы избежать исключения)
if (value == 0) return 0;
// Заполняем все биты справа от старшего единицей: превращаем число в 2^n - 1
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
// Умножение на константу De Bruijn и сдвиг для получения индекса в таблице
return (int)Log2DeBruijn32[(value * 0x07C4ACDDu) >> 27];
}
/// <summary>64-битный логарифм по основанию 2 (округление вниз). Для value = 0 возвращает 0.</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Log2(ulong value)
{
if (value == 0) { return 0; }
uint high = (uint)(value >> 32);
if (high == 0)
{
return Log2((uint)value);
}
else
{
return 32 + Log2(high);
}
}
} }
#if ENABLE_IL2CPP #if ENABLE_IL2CPP
[Il2CppSetOption(Option.NullChecks, false)] [Il2CppSetOption(Option.NullChecks, false)]
@ -44,6 +115,18 @@ namespace DCFApixels.DragonECS.Core.Internal
return Comparison(x, y); return Comparison(x, y);
} }
} }
internal readonly struct StructComparer<T> : IComparer<T>
{
public readonly Comparer<T> Comparer;
public StructComparer(Comparer<T> comparer)
{
Comparer = comparer;
}
public int Compare(T x, T y)
{
return Comparer.Compare(x, y);
}
}
// a > b = return > 0 // a > b = return > 0
// int Compare(T a, T b); // int Compare(T a, T b);
@ -126,7 +209,7 @@ namespace DCFApixels.DragonECS.Core.Internal
//Debug.Assert(comparer != null); //Debug.Assert(comparer != null);
if (keys.Length > 1) if (keys.Length > 1)
{ {
IntroSort(keys, 2 * (BitOperations.Log2((uint)keys.Length) + 1), ref comparer); IntroSort(keys, 2 * (ArraySortUtility.Log2((uint)keys.Length) + 1), ref comparer);
} }
} }

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: a591de1858028504d819333121bfddd6 guid: fe9273da3e82bfd48983415b1726aed1
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2