diff --git a/Projects/Benchmarks/Benchmarks.csproj b/Projects/Benchmarks/Benchmarks.csproj
index eff9ed660..ca226bba4 100644
--- a/Projects/Benchmarks/Benchmarks.csproj
+++ b/Projects/Benchmarks/Benchmarks.csproj
@@ -10,6 +10,8 @@
+
+
diff --git a/Projects/Benchmarks/Benchmarks/Map/MapEntitiesSelectors.cs b/Projects/Benchmarks/Benchmarks/Map/MapEntitiesSelectors.cs
new file mode 100644
index 000000000..7348824c8
--- /dev/null
+++ b/Projects/Benchmarks/Benchmarks/Map/MapEntitiesSelectors.cs
@@ -0,0 +1,545 @@
+using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Jobs;
+using NetFabric.Hyperlinq;
+using Server;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using static NetFabric.Hyperlinq.ArrayExtensions;
+
+namespace Benchmarks.EntitiesSelectors
+{
+ [SimpleJob(RuntimeMoniker.Net60)]
+ [MemoryDiagnoser]
+ public class MapEntitiesSelectors
+ {
+ private static readonly Sector sector = new();
+ private static readonly Point3D[] locations = new[] { new Point3D(0, 0, 0), new Point3D(50, 50, 0) };
+
+ public static Rectangle2D[] BoundsArray() => new[]
+ {
+ new Rectangle2D(70, 70, 100, 100),
+ new Rectangle2D(30, 30, 100, 100),
+ new Rectangle2D(0, 0, 100, 100),
+ };
+
+ [GlobalSetup]
+ public static void Init()
+ {
+ for (int j = 0; j < locations.Length; j++)
+ {
+ Point3D loc = locations[j];
+
+ for (int i = 0; i < 500; ++i)
+ {
+ sector.BItems.Add(new BItem(loc));
+ }
+
+ for (int i = 0; i < 25; ++i)
+ {
+ sector.Mobiles.Add(new Mobile(loc));
+ }
+ }
+ }
+
+ [ParamsSource(nameof(BoundsArray))]
+ public Rectangle2D bounds;
+
+ [Benchmark(Baseline = true)]
+ public IEntity SelectEntitiesFor()
+ {
+ IEntity toRet = null;
+ for (int i = sector.Mobiles.Count - 1; i >= 0; --i)
+ {
+ Mobile mob = sector.Mobiles[i];
+ if (mob is { Deleted: false } tMob && bounds.Contains(mob.Location))
+ {
+ toRet = tMob;
+ }
+ }
+
+ for (int i = sector.BItems.Count - 1; i >= 0; --i)
+ {
+ BItem item = sector.BItems[i];
+ if (item is { Deleted: false, Parent: null } tItem && bounds.Contains(item.Location))
+ {
+ toRet = tItem;
+ }
+ }
+
+ return toRet;
+ }
+
+ [Benchmark]
+ public IEntity SelectEntitiesNew()
+ {
+ IEntity toRet = null;
+ foreach (IEntity e in SelectEntitiesNew(sector, bounds))
+ {
+ toRet = e;
+ }
+
+ return toRet;
+ }
+
+ [Benchmark]
+ public IEntity SelectEntitiesLinq()
+ {
+ IEntity toRet = null;
+ foreach (IEntity e in SelectEntitiesLinq(sector, bounds))
+ {
+ toRet = e;
+ }
+
+ return toRet;
+ }
+
+ [Benchmark]
+ public IEntity SelectMobilesHyperLinq()
+ {
+ IEntity toRet = null;
+ foreach (IEntity e in SelectEntitiesHyperlinq(sector, bounds))
+ {
+ toRet = e;
+ }
+
+ return toRet;
+ }
+
+
+ public IEnumerable SelectEntitiesLinq(Sector s, Rectangle2D bounds)
+ {
+ return Enumerable.Empty()
+ .Union(s.Mobiles.Where(o => o is { Deleted: false } && bounds.Contains(o.Location)))
+ .Union(s.BItems.Where(o => o is { Deleted: false, Parent: null } && bounds.Contains(o.Location)));
+ }
+
+ private readonly List entities = new(10);
+
+ public IEnumerable SelectEntitiesNew(Sector s, Rectangle2D bounds)
+ {
+ entities.Clear();
+ entities.EnsureCapacity(s.Mobiles.Count + s.BItems.Count);
+
+ for (int i = s.Mobiles.Count - 1, j = s.BItems.Count - 1; i >= 0 || j >= 0; --i, --j)
+ {
+ if (j >= 0)
+ {
+ BItem BItem = s.BItems[j];
+ if (BItem is { Deleted: false, Parent: null } && bounds.Contains(BItem.Location))
+ {
+ entities.Add(BItem);
+ }
+ }
+ if (i >= 0)
+ {
+ Mobile mob = s.Mobiles[i];
+ if (mob is { Deleted: false } && bounds.Contains(mob.Location))
+ {
+ entities.Add(mob);
+ }
+ }
+ }
+ return entities;
+ }
+
+ public IEnumerable SelectEntitiesHyperlinq(Sector s, Rectangle2D bounds)
+ {
+ ArraySegmentWhereSelectEnumerable> mobiles =
+ s.Mobiles.AsValueEnumerable().Where(new MobileWhereHyper(bounds)).Select>();
+
+ ArraySegmentWhereSelectEnumerable> items =
+ s.BItems.AsValueEnumerable().Where(new BItemWhereHyper(bounds)).Select>();
+
+ return mobiles.Concat(items);
+ }
+ }
+
+ public class BItem : IPoint3D, IEntity
+ {
+ public object Parent { get; set; } = null;
+
+ public bool Deleted { get; set; } = false;
+
+ public int Z { get; set; } = 1;
+
+ public int X { get; set; } = 1;
+
+ public int Y { get; set; } = 1;
+
+ public Serial Serial => throw new NotImplementedException();
+
+ public Point3D Location { get; }
+ public Map Map { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+
+ public Region Region => throw new NotImplementedException();
+
+ public string Name { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ public int Hue { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ public Direction Direction { get => throw new System.NotImplementedException(); set => throw new NotImplementedException(); }
+ public DateTime Created { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+
+ public int TypeRef => throw new NotImplementedException();
+
+ Point3D IEntity.Location => Location;
+
+ Map IEntity.Map => throw new NotImplementedException();
+
+ int IPoint3D.Z => throw new NotImplementedException();
+
+ int IPoint2D.X => throw new NotImplementedException();
+
+ int IPoint2D.Y => throw new NotImplementedException();
+
+ DateTime ISerializable.Created { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ DateTime ISerializable.LastSerialized { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ long ISerializable.SavePosition { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ BufferWriter ISerializable.SaveBuffer { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+
+ int ISerializable.TypeRef => throw new NotImplementedException();
+
+ Serial ISerializable.Serial => throw new NotImplementedException();
+
+ bool ISerializable.Deleted => throw new NotImplementedException();
+
+ public BItem(Point3D location)
+ {
+ Location = location;
+ }
+
+ public void Delete()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void ProcessDelta()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void OnStatsQuery(Server.Mobile m)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void InvalidateProperties()
+ {
+ throw new NotImplementedException();
+ }
+
+ public int CompareTo(object obj)
+ {
+ throw new NotImplementedException();
+ }
+
+ public int CompareTo(IEntity other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void MoveToWorld(Point3D location, Map map)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool InRange(Point2D p, int range)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool InRange(Point3D p, int range)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void RemoveBItem(BItem BItem)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void BeforeSerialize()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Deserialize(IGenericReader reader)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Serialize(IGenericWriter writer)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void SetTypeRef(Type type)
+ {
+ throw new NotImplementedException();
+ }
+
+ void IEntity.MoveToWorld(Point3D location, Map map)
+ {
+ throw new NotImplementedException();
+ }
+
+ void IEntity.ProcessDelta()
+ {
+ throw new NotImplementedException();
+ }
+
+ bool IEntity.InRange(Point2D p, int range)
+ {
+ throw new NotImplementedException();
+ }
+
+ bool IEntity.InRange(Point3D p, int range)
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.BeforeSerialize()
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.Deserialize(IGenericReader reader)
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.Serialize(IGenericWriter writer)
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.Delete()
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.SetTypeRef(Type type)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void RemoveItem(Item item)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public class Mobile : IPoint3D, IEntity
+ {
+ public bool Deleted { get; set; } = false;
+
+ public int Z { get; set; } = 1;
+
+ public int X { get; set; } = 1;
+
+ public int Y { get; set; } = 1;
+
+ public Serial Serial => throw new NotImplementedException();
+
+ public Point3D Location { get; }
+ public Map Map { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+
+ public Region Region => throw new NotImplementedException();
+
+ public string Name { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ public int Hue { get => throw new System.NotImplementedException(); set => throw new NotImplementedException(); }
+ public Direction Direction { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ public DateTime Created { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+
+ public int TypeRef => throw new NotImplementedException();
+
+ Point3D IEntity.Location => Location;
+
+ Map IEntity.Map => throw new NotImplementedException();
+
+ int IPoint3D.Z => throw new NotImplementedException();
+
+ int IPoint2D.X => throw new NotImplementedException();
+
+ int IPoint2D.Y => throw new NotImplementedException();
+
+ DateTime ISerializable.Created { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ DateTime ISerializable.LastSerialized { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ long ISerializable.SavePosition { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ BufferWriter ISerializable.SaveBuffer { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+
+ int ISerializable.TypeRef => throw new NotImplementedException();
+
+ Serial ISerializable.Serial => throw new NotImplementedException();
+
+ bool ISerializable.Deleted => throw new NotImplementedException();
+
+ public Mobile(Point3D location)
+ {
+ Location = location;
+ }
+
+ public void Delete()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void ProcessDelta()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void OnStatsQuery(Server.Mobile m)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void InvalidateProperties()
+ {
+ throw new NotImplementedException();
+ }
+
+ public int CompareTo(object obj)
+ {
+ throw new NotImplementedException();
+ }
+
+ public int CompareTo(IEntity other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void MoveToWorld(Point3D location, Map map)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool InRange(Point2D p, int range)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool InRange(Point3D p, int range)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void RemoveBItem(BItem BItem)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void BeforeSerialize()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Deserialize(IGenericReader reader)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Serialize(IGenericWriter writer)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void SetTypeRef(Type type)
+ {
+ throw new NotImplementedException();
+ }
+
+ void IEntity.MoveToWorld(Point3D location, Map map)
+ {
+ throw new NotImplementedException();
+ }
+
+ void IEntity.ProcessDelta()
+ {
+ throw new NotImplementedException();
+ }
+
+ bool IEntity.InRange(Point2D p, int range)
+ {
+ throw new NotImplementedException();
+ }
+
+ bool IEntity.InRange(Point3D p, int range)
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.BeforeSerialize()
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.Deserialize(IGenericReader reader)
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.Serialize(IGenericWriter writer)
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.Delete()
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.SetTypeRef(Type type)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void RemoveItem(Item item)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public class Sector
+ {
+ public List BItems { get; set; } = new List();
+ public List Mobiles { get; set; } = new List();
+ }
+
+ public struct BItemWhereHyper : NetFabric.Hyperlinq.IFunction
+ {
+ private readonly Rectangle2D bounds;
+
+ public BItemWhereHyper(Rectangle2D bounds)
+ {
+ this.bounds = bounds;
+ }
+
+ public bool Invoke(BItem element)
+ {
+ return element is { Deleted: false, Parent: null } && bounds.Contains(element.Location);
+ }
+ }
+
+ public struct MobileWhereHyper : NetFabric.Hyperlinq.IFunction
+ {
+ private readonly Rectangle2D bounds;
+
+ public MobileWhereHyper(Rectangle2D bounds)
+ {
+ this.bounds = bounds;
+ }
+
+ public bool Invoke(Mobile element)
+ {
+ return element is { Deleted: false } && bounds.Contains(element.Location);
+ }
+ }
+
+ public struct SelectHyper : NetFabric.Hyperlinq.IFunction where TSource : TDest
+ {
+ public TDest Invoke(TSource arg)
+ {
+ return arg;
+ }
+ }
+}
diff --git a/Projects/Benchmarks/Benchmarks/Map/MapItemSelectors.cs b/Projects/Benchmarks/Benchmarks/Map/MapItemSelectors.cs
new file mode 100644
index 000000000..8eb1758d2
--- /dev/null
+++ b/Projects/Benchmarks/Benchmarks/Map/MapItemSelectors.cs
@@ -0,0 +1,403 @@
+using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Jobs;
+using NetFabric.Hyperlinq;
+using Server;
+using StructLinq;
+using StructLinq.Array;
+using StructLinq.List;
+using StructLinq.Select;
+using StructLinq.Where;
+using System;
+using System.Buffers;
+using System.Collections.Generic;
+using System.Linq;
+using static NetFabric.Hyperlinq.ArrayExtensions;
+
+namespace Benchmarks.ItemSelectors
+{
+ [SimpleJob(RuntimeMoniker.Net60)]
+ [MemoryDiagnoser]
+ public class MapItemSelectors
+ {
+ private static readonly Sector sector = new();
+ private static readonly Point3D[] locations = new[] { new Point3D(0, 0, 0), new Point3D(50, 50, 0) };
+
+ public static Rectangle2D[] BoundsArray() => new[]
+ {
+ new Rectangle2D(70, 70, 100, 100),
+ new Rectangle2D(30, 30, 100, 100),
+ new Rectangle2D(0, 0, 100, 100),
+ };
+
+ [GlobalSetup]
+ public static void Init()
+ {
+ for (int j = 0; j < locations.Length; j++)
+ {
+ Point3D loc = locations[j];
+
+ for (int i = 0; i < 500; ++i)
+ {
+ sector.BItems.Add(new BItemDerived(loc));
+ }
+ }
+ }
+
+ [ParamsSource(nameof(BoundsArray))]
+ public Rectangle2D bounds;
+
+ [Benchmark(Baseline = true)]
+ public BItemDerived SelectBItemsFor()
+ {
+ BItemDerived toRet = null;
+ for (int i = sector.BItems.Count - 1; i >= 0; --i)
+ {
+ BItem BItem = sector.BItems[i];
+ if (BItem is BItemDerived { Deleted: false, Parent: null } tItem && bounds.Contains(BItem.Location))
+ {
+ toRet = tItem;
+ }
+ }
+
+ return toRet;
+ }
+
+ [Benchmark]
+ public BItemDerived SelectBItemsNew()
+ {
+ BItemDerived toRet = null;
+ foreach (BItemDerived i in SelectBItems(sector, bounds))
+ {
+ toRet = i;
+ }
+
+ return toRet;
+ }
+
+ [Benchmark]
+ public BItemDerived SelectBItemsLinq()
+ {
+ BItemDerived toRet = null;
+ foreach (BItemDerived i in SelectBItemsLinq(sector, bounds))
+ {
+ toRet = i;
+ }
+
+ return toRet;
+ }
+
+ [Benchmark]
+ public BItemDerived SelectBItemsLinqStruct()
+ {
+ BItemDerived toRet = null;
+ foreach (BItemDerived i in SelectBItemsLinqStruct(sector, bounds))
+ {
+ toRet = i;
+ }
+
+ return toRet;
+ }
+
+ [Benchmark]
+ public BItemDerived SelectBItemsLinqStructInterface()
+ {
+ BItemDerived toRet = null;
+ IEnumerable enumerable = SelectBItemsLinqStruct(sector, bounds).ToEnumerable();
+
+ foreach (BItemDerived i in enumerable)
+ {
+ toRet = i;
+ }
+
+ return toRet;
+ }
+
+ [Benchmark]
+ public BItemDerived SelectBItemsHyperLinq()
+ {
+ BItemDerived toRet = null;
+ foreach (BItemDerived i in SelectBItemsHyperlinq(sector, bounds))
+ {
+ toRet = i;
+ }
+
+ return toRet;
+ }
+
+ [Benchmark]
+ public BItemDerived SelectBItemsHyperLinqInterface()
+ {
+ BItemDerived toRet = null;
+ IEnumerable enumerable = SelectBItemsHyperlinq(sector, bounds);
+
+ foreach (BItemDerived i in enumerable)
+ {
+ toRet = i;
+ }
+
+ return toRet;
+ }
+
+ [Benchmark]
+ public BItemDerived SelectBItemsHyperLinqArrayPool()
+ {
+ BItemDerived toRet = null;
+ using Lease lease = SelectBItemsHyperlinq(sector, bounds).ToArray(ArrayPool.Shared);
+
+ foreach (BItemDerived i in lease)
+ {
+ toRet = i;
+ }
+
+ return toRet;
+ }
+
+ public IEnumerable SelectBItemsLinq(Sector s, Rectangle2D bounds) where T : BItem
+ {
+ return s.BItems.OfType().Where(o => o is { Deleted: false, Parent: null } && bounds.Contains(o.Location));
+ }
+
+ public IEnumerable SelectBItems(Sector s, Rectangle2D bounds) where T : BItem
+ {
+ List items = s.BItems;
+ List entities = new(items.Count);
+
+ for (int i = items.Count - 1; i >= 0; --i)
+ {
+ if (items[i] is T { Deleted: false, Parent: null } tItem && bounds.Contains(tItem.Location))
+ {
+ entities.Add(tItem);
+ }
+ }
+ return entities;
+ }
+
+ public SelectEnumerable, ArrayStructEnumerator, BItemWhere>,
+ WhereEnumerator, BItemWhere>, BItemSelect>
+ SelectBItemsLinqStruct(Sector s, Rectangle2D bounds) where T : BItem
+ {
+ BItemWhere bitemWhere = new(bounds);
+ BItemSelect bitemSelect = new();
+
+ return s.BItems.ToStructEnumerable()
+ .Where(ref bitemWhere, x => x)
+ .Select(ref bitemSelect, x => x, x => x);
+ }
+
+ public ArraySegmentWhereSelectEnumerable, SelectHyper>
+ SelectBItemsHyperlinq(Sector s, Rectangle2D bounds) where T : BItem
+ {
+ return s.BItems.AsValueEnumerable()
+ .Where(new BItemWhereHyper(bounds))
+ .Select>();
+ }
+ }
+
+ public class BItem : IPoint3D, IEntity
+ {
+ public object Parent { get; set; } = null;
+
+ public bool Deleted { get; set; } = false;
+
+ public int Z { get; set; } = 1;
+
+ public int X { get; set; } = 1;
+
+ public int Y { get; set; } = 1;
+
+ public Serial Serial => throw new NotImplementedException();
+
+ public Point3D Location { get; }
+
+ public Map Map { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+
+ public Region Region => throw new NotImplementedException();
+
+ public string Name { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ public int Hue { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ public Direction Direction { get => throw new System.NotImplementedException(); set => throw new NotImplementedException(); }
+ public DateTime Created { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+
+ public int TypeRef => throw new NotImplementedException();
+
+ Point3D IEntity.Location => Location;
+
+ int IPoint3D.Z => throw new NotImplementedException();
+
+ int IPoint2D.X => throw new NotImplementedException();
+
+ int IPoint2D.Y => throw new NotImplementedException();
+
+ DateTime ISerializable.Created { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ DateTime ISerializable.LastSerialized { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ long ISerializable.SavePosition { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ BufferWriter ISerializable.SaveBuffer { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+
+ int ISerializable.TypeRef => throw new NotImplementedException();
+
+ Serial ISerializable.Serial => throw new NotImplementedException();
+
+ bool ISerializable.Deleted => throw new NotImplementedException();
+
+ public BItem(Point3D location)
+ {
+ Location = location;
+ }
+
+ public void Delete()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void ProcessDelta()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void OnStatsQuery(Server.Mobile m)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void InvalidateProperties()
+ {
+ throw new NotImplementedException();
+ }
+
+ public int CompareTo(object obj)
+ {
+ throw new NotImplementedException();
+ }
+
+ public int CompareTo(IEntity other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void MoveToWorld(Point3D location, Map map)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool InRange(Point2D p, int range)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool InRange(Point3D p, int range)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void RemoveBItem(BItem BItem)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void BeforeSerialize()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Deserialize(IGenericReader reader)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Serialize(IGenericWriter writer)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void SetTypeRef(Type type)
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.BeforeSerialize()
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.Deserialize(IGenericReader reader)
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.Serialize(IGenericWriter writer)
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.Delete()
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.SetTypeRef(Type type)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void RemoveItem(Item item)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public class BItemDerived : BItem
+ {
+ public BItemDerived(Point3D location) : base(location) { }
+ }
+
+ public class Sector
+ {
+ public List BItems { get; set; } = new List();
+ }
+
+ public struct BItemWhere : StructLinq.IFunction where T : BItem
+ {
+ private readonly Rectangle2D bounds;
+
+ public BItemWhere(Rectangle2D bounds)
+ {
+ this.bounds = bounds;
+ }
+
+ public bool Eval(BItem element)
+ {
+ return element is T { Deleted: false, Parent: null } && bounds.Contains(element.Location);
+ }
+ }
+
+ public struct BItemSelect : StructLinq.IFunction where T : BItem
+ {
+ public T Eval(BItem element)
+ {
+ return (T)element;
+ }
+ }
+
+ public struct BItemWhereHyper : NetFabric.Hyperlinq.IFunction where T : BItem
+ {
+ private readonly Rectangle2D bounds;
+
+ public BItemWhereHyper(Rectangle2D bounds)
+ {
+ this.bounds = bounds;
+ }
+
+ public bool Invoke(BItem element)
+ {
+ return element is T { Deleted: false, Parent: null } && bounds.Contains(element.Location);
+ }
+ }
+
+ public struct SelectHyper : NetFabric.Hyperlinq.IFunction where TDest : TSource
+ {
+ public TDest Invoke(TSource arg)
+ {
+ return (TDest)arg;
+ }
+ }
+}
diff --git a/Projects/Benchmarks/Benchmarks/Map/MapMobileSelectors.cs b/Projects/Benchmarks/Benchmarks/Map/MapMobileSelectors.cs
new file mode 100644
index 000000000..c9932070f
--- /dev/null
+++ b/Projects/Benchmarks/Benchmarks/Map/MapMobileSelectors.cs
@@ -0,0 +1,255 @@
+using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Jobs;
+using NetFabric.Hyperlinq;
+using Server;
+using StructLinq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using static NetFabric.Hyperlinq.ArrayExtensions;
+
+namespace Benchmarks.MobileSelectors
+{
+ [SimpleJob(RuntimeMoniker.Net60)]
+ [MemoryDiagnoser]
+ public class MapMobileSelectors
+ {
+ private static readonly Sector sector = new();
+ private static readonly Point3D[] locations = new[] { new Point3D(0, 0, 0), new Point3D(50, 50, 0) };
+
+ public static Rectangle2D[] BoundsArray() => new[]
+ {
+ new Rectangle2D(70, 70, 100, 100),
+ new Rectangle2D(30, 30, 100, 100),
+ new Rectangle2D(0, 0, 100, 100),
+ };
+
+ [GlobalSetup]
+ public static void Init()
+ {
+ for (int j = 0; j < locations.Length; j++)
+ {
+ Point3D loc = locations[j];
+
+ for (int i = 0; i < 500; ++i)
+ {
+ sector.Mobiles.Add(new MobileDerived(loc));
+ }
+ }
+ }
+
+ [ParamsSource(nameof(BoundsArray))]
+ public Rectangle2D bounds;
+
+ [Benchmark(Baseline = true)]
+ public MobileDerived SelectMobilesFor()
+ {
+ MobileDerived toRet = null;
+ for (int i = sector.Mobiles.Count - 1; i >= 0; --i)
+ {
+ Mobile mob = sector.Mobiles[i];
+ if (mob is MobileDerived { Deleted: false } tMob && bounds.Contains(mob.Location))
+ {
+ toRet = tMob;
+ }
+ }
+
+ return toRet;
+ }
+
+ [Benchmark]
+ public MobileDerived SelectMobilesNew()
+ {
+ MobileDerived toRet = null;
+ foreach (MobileDerived m in SelectMobiles(sector, bounds))
+ {
+ toRet = m;
+ }
+
+ return toRet;
+ }
+
+ [Benchmark]
+ public MobileDerived SelectMobilesLinq()
+ {
+ MobileDerived toRet = null;
+ foreach (MobileDerived m in SelectMobilesLinq(sector, bounds))
+ {
+ toRet = m;
+ }
+
+ return toRet;
+ }
+
+ [Benchmark]
+ public MobileDerived SelectMobilesHyperLinq()
+ {
+ MobileDerived toRet = null;
+ foreach (MobileDerived m in SelectMobilesHyperlinq(sector, bounds))
+ {
+ toRet = m;
+ }
+
+ return toRet;
+ }
+
+ public IEnumerable SelectMobilesLinq(Sector s, Rectangle2D bounds) where T : Mobile
+ {
+ return s.Mobiles.OfType().Where(o => o is { Deleted: false } && bounds.Contains(o.Location));
+ }
+
+ public IEnumerable SelectMobiles(Sector s, Rectangle2D bounds) where T : Mobile
+ {
+ List mobiles = s.Mobiles;
+ List entities = new(mobiles.Count);
+
+ for (int i = mobiles.Count - 1; i >= 0; --i)
+ {
+ if (mobiles[i] is T { Deleted: false } tMob && bounds.Contains(tMob.Location))
+ {
+ entities.Add(tMob);
+ }
+ }
+ return entities;
+ }
+
+ public ArraySegmentWhereSelectEnumerable, SelectHyper>
+ SelectMobilesHyperlinq(Sector s, Rectangle2D bounds) where T : Mobile
+ {
+ return s.Mobiles.AsValueEnumerable()
+ .Where(new MobileWhereHyper(bounds))
+ .Select>();
+ }
+ }
+
+ public class Mobile : IPoint3D, IEntity
+ {
+ public bool Deleted { get; set; } = false;
+
+ public int Z { get; set; } = 1;
+
+ public int X { get; set; } = 1;
+
+ public int Y { get; set; } = 1;
+
+ public Serial Serial => throw new NotImplementedException();
+
+ public Point3D Location { get; }
+
+ public Map Map { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+
+ public Region Region => throw new NotImplementedException();
+
+ public string Name { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ public int Hue { get => throw new System.NotImplementedException(); set => throw new NotImplementedException(); }
+ public Direction Direction { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ public DateTime Created { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+
+ public int TypeRef => throw new NotImplementedException();
+
+ int IPoint3D.Z => throw new NotImplementedException();
+
+ int IPoint2D.X => throw new NotImplementedException();
+
+ int IPoint2D.Y => throw new NotImplementedException();
+
+ DateTime ISerializable.Created { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ DateTime ISerializable.LastSerialized { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ long ISerializable.SavePosition { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ BufferWriter ISerializable.SaveBuffer { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+
+ int ISerializable.TypeRef => throw new NotImplementedException();
+
+ Serial ISerializable.Serial => throw new NotImplementedException();
+
+ bool ISerializable.Deleted => throw new NotImplementedException();
+
+ public Mobile(Point3D location)
+ {
+ Location = location;
+ }
+
+ public void MoveToWorld(Point3D location, Map map)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void ProcessDelta()
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool InRange(Point2D p, int range)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool InRange(Point3D p, int range)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void RemoveItem(Item item)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void BeforeSerialize()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Deserialize(IGenericReader reader)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Serialize(IGenericWriter writer)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Delete()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void SetTypeRef(Type type)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public class MobileDerived : Mobile
+ {
+ public MobileDerived(Point3D location) : base(location) { }
+ }
+
+ public class Sector
+ {
+ public List Mobiles { get; set; } = new List();
+ }
+
+ public struct MobileWhereHyper : NetFabric.Hyperlinq.IFunction where T : Mobile
+ {
+ private readonly Rectangle2D bounds;
+
+ public MobileWhereHyper(Rectangle2D bounds)
+ {
+ this.bounds = bounds;
+ }
+
+ public bool Invoke(Mobile element)
+ {
+ return element is T { Deleted: false } && bounds.Contains(element.Location);
+ }
+ }
+
+ public struct SelectHyper : NetFabric.Hyperlinq.IFunction where TDest : TSource
+ {
+ public TDest Invoke(TSource arg)
+ {
+ return (TDest)arg;
+ }
+ }
+}
diff --git a/Projects/Benchmarks/Benchmarks/Map/MapMultiSelectors.cs b/Projects/Benchmarks/Benchmarks/Map/MapMultiSelectors.cs
new file mode 100644
index 000000000..e5c6605f5
--- /dev/null
+++ b/Projects/Benchmarks/Benchmarks/Map/MapMultiSelectors.cs
@@ -0,0 +1,311 @@
+using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Jobs;
+using NetFabric.Hyperlinq;
+using Server;
+using StructLinq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using static NetFabric.Hyperlinq.ArrayExtensions;
+
+namespace Benchmarks.MultiSelectors
+{
+ [SimpleJob(RuntimeMoniker.Net60)]
+ [MemoryDiagnoser]
+ public class MapMultiSelectors
+ {
+ private static readonly Sector sector = new();
+ private static readonly Point3D[] locations = new[] { new Point3D(0, 0, 0), new Point3D(50, 50, 0) };
+
+ public static Rectangle2D[] BoundsArray() => new[]
+ {
+ new Rectangle2D(70, 70, 100, 100),
+ new Rectangle2D(30, 30, 100, 100),
+ new Rectangle2D(0, 0, 100, 100),
+ };
+
+ [GlobalSetup]
+ public static void Init()
+ {
+ for (int j = 0; j < locations.Length; j++)
+ {
+ Point3D loc = locations[j];
+
+ for (int i = 0; i < 25; ++i)
+ {
+ sector.Multis.Add(new BaseMulti(loc));
+ }
+ }
+ }
+
+ [ParamsSource(nameof(BoundsArray))]
+ public Rectangle2D bounds;
+
+ [Benchmark(Baseline = true)]
+ public BaseMulti SelectMultiFor()
+ {
+ BaseMulti toRet = null;
+ for (int i = sector.Multis.Count - 1; i >= 0; --i)
+ {
+ BaseMulti multi = sector.Multis[i];
+ if (multi is { Deleted: false } tMulti && bounds.Contains(multi.Location))
+ {
+ toRet = tMulti;
+ }
+ }
+
+ return toRet;
+ }
+
+ [Benchmark]
+ public BaseMulti SelectMultiNew()
+ {
+ BaseMulti toRet = null;
+ foreach (BaseMulti m in SelectMultiNew(sector, bounds))
+ {
+ toRet = m;
+ }
+
+ return toRet;
+ }
+
+ [Benchmark]
+ public BaseMulti SelectMultiLinq()
+ {
+ BaseMulti toRet = null;
+ foreach (BaseMulti m in SelectMultiLinq(sector, bounds))
+ {
+ toRet = m;
+ }
+
+ return toRet;
+ }
+
+ [Benchmark]
+ public BaseMulti SelectMultiHyperLinq()
+ {
+ BaseMulti toRet = null;
+ foreach (BaseMulti m in SelectMultiHyperlinq(sector, bounds))
+ {
+ toRet = m;
+ }
+
+ return toRet;
+ }
+
+ public IEnumerable SelectMultiLinq(Sector s, Rectangle2D bounds)
+ {
+ return s.Multis.Where(o => o is { Deleted: false } && bounds.Contains(o.Location));
+ }
+
+ public IEnumerable SelectMultiNew(Sector s, Rectangle2D bounds)
+ {
+ List entities = new(s.Multis.Count);
+
+ for (int i = s.Multis.Count - 1; i >= 0; --i)
+ {
+ BaseMulti multiItem = s.Multis[i];
+ if (multiItem is { Deleted: false } && bounds.Contains(multiItem.Location))
+ {
+ entities.Add(multiItem);
+ }
+ }
+ return entities;
+ }
+
+ public ArraySegmentWhereEnumerable
+ SelectMultiHyperlinq(Sector s, Rectangle2D bounds)
+ {
+ return s.Multis.AsValueEnumerable().Where(new MultiWhereHyper(bounds));
+ }
+ }
+
+ public class BItem : IPoint3D, IEntity
+ {
+ public object Parent { get; set; } = null;
+
+ public bool Deleted { get; set; } = false;
+
+ public int Z { get; set; } = 1;
+
+ public int X { get; set; } = 1;
+
+ public int Y { get; set; } = 1;
+
+ public Serial Serial => throw new NotImplementedException();
+
+ public Point3D Location { get; }
+
+ public Map Map { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+
+ public Region Region => throw new NotImplementedException();
+
+ public string Name { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ public int Hue { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ public Direction Direction { get => throw new System.NotImplementedException(); set => throw new NotImplementedException(); }
+ public DateTime Created { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+
+ public int TypeRef => throw new NotImplementedException();
+
+ int IPoint3D.Z => throw new NotImplementedException();
+
+ int IPoint2D.X => throw new NotImplementedException();
+
+ int IPoint2D.Y => throw new NotImplementedException();
+
+ DateTime ISerializable.Created { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ DateTime ISerializable.LastSerialized { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ long ISerializable.SavePosition { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ BufferWriter ISerializable.SaveBuffer { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+
+ int ISerializable.TypeRef => throw new NotImplementedException();
+
+ Serial ISerializable.Serial => throw new NotImplementedException();
+
+ bool ISerializable.Deleted => throw new NotImplementedException();
+
+ public BItem(Point3D location)
+ {
+ Location = location;
+ }
+
+ public void Delete()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void ProcessDelta()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void OnStatsQuery(Server.Mobile m)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void InvalidateProperties()
+ {
+ throw new NotImplementedException();
+ }
+
+ public int CompareTo(object obj)
+ {
+ throw new NotImplementedException();
+ }
+
+ public int CompareTo(IEntity other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void MoveToWorld(Point3D location, Map map)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool InRange(Point2D p, int range)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool InRange(Point3D p, int range)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void RemoveBItem(BItem BItem)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void BeforeSerialize()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Deserialize(IGenericReader reader)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Serialize(IGenericWriter writer)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void SetTypeRef(Type type)
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.BeforeSerialize()
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.Deserialize(IGenericReader reader)
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.Serialize(IGenericWriter writer)
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.Delete()
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.SetTypeRef(Type type)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void RemoveItem(Item item)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public class BaseMulti : BItem
+ {
+ public MultiComponentList Components = MultiComponentList.Empty;
+
+ public BaseMulti(Point3D location) : base(location)
+ {
+ for (int i = 0; i < 20; ++i)
+ {
+ for (int j = 0; j < 20; ++j)
+ {
+ for (int z = 0; z < 20; ++z)
+ {
+ Components.Add(123, i, j, z);
+ }
+ }
+ }
+ }
+ }
+
+ public class Sector
+ {
+ public List Multis { get; set; } = new List();
+ }
+
+ public struct MultiWhereHyper : NetFabric.Hyperlinq.IFunction
+ {
+ private readonly Rectangle2D bounds;
+
+ public MultiWhereHyper(Rectangle2D bounds)
+ {
+ this.bounds = bounds;
+ }
+
+ public bool Invoke(BaseMulti element)
+ {
+ return element is { Deleted: false } && bounds.Contains(element.Location);
+ }
+ }
+}
diff --git a/Projects/Benchmarks/Benchmarks/Map/MapMultiTilesSelectors.cs b/Projects/Benchmarks/Benchmarks/Map/MapMultiTilesSelectors.cs
new file mode 100644
index 000000000..553016f93
--- /dev/null
+++ b/Projects/Benchmarks/Benchmarks/Map/MapMultiTilesSelectors.cs
@@ -0,0 +1,352 @@
+using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Jobs;
+using NetFabric.Hyperlinq;
+using Server;
+using StructLinq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Benchmarks.MultiTilesSelectors
+{
+ [SimpleJob(RuntimeMoniker.Net60)]
+ [MemoryDiagnoser]
+ public class MapMultiTilesSelectors
+ {
+ private static readonly Sector sector = new();
+ private static readonly Point3D[] locations = new[] { new Point3D(0, 0, 0), new Point3D(50, 50, 0) };
+
+ public static Rectangle2D[] BoundsArray() => new[]
+ {
+ new Rectangle2D(70, 70, 100, 100),
+ new Rectangle2D(30, 30, 100, 100),
+ new Rectangle2D(0, 0, 100, 100),
+ };
+
+ [GlobalSetup]
+ public static void Init()
+ {
+ for (int j = 0; j < locations.Length; j++)
+ {
+ Point3D loc = locations[j];
+
+ for (int i = 0; i < 25; ++i)
+ {
+ sector.Multis.Add(new BaseMulti(loc));
+ }
+ }
+ }
+
+ [ParamsSource(nameof(BoundsArray))]
+ public Rectangle2D bounds;
+
+ [Benchmark]
+ public int SelectMultiTilesNew()
+ {
+ int toRet = 0;
+
+ foreach (StaticTile[] tiles in SelectMultiTilesNew(sector, bounds))
+ {
+ for (int i = 0; i < tiles.Length; ++i)
+ {
+ toRet = tiles[i].ID;
+ }
+ }
+
+ return toRet;
+ }
+
+ [Benchmark(Baseline = true)]
+ public int SelectMultiTilesLinq()
+ {
+ int toRet = 0;
+
+ foreach (StaticTile[] tiles in SelectMultiTilesLinq(sector, bounds))
+ {
+ for (int i = 0; i < tiles.Length; ++i)
+ {
+ toRet = tiles[i].ID;
+ }
+ }
+
+ return toRet;
+ }
+
+ public IEnumerable SelectMultiTilesLinq(Sector s, Rectangle2D bounds)
+ {
+ foreach (var o in s.Multis.Where(o => o != null && !o.Deleted))
+ {
+ var c = o.Components;
+
+ int x, y, xo, yo;
+ StaticTile[] t, r;
+
+ for (x = bounds.Start.X; x < bounds.End.X; x++)
+ {
+ xo = x - (o.X + c.Min.X);
+
+ if (xo < 0 || xo >= c.Width)
+ {
+ continue;
+ }
+
+ for (y = bounds.Start.Y; y < bounds.End.Y; y++)
+ {
+ yo = y - (o.Y + c.Min.Y);
+
+ if (yo < 0 || yo >= c.Height)
+ {
+ continue;
+ }
+
+ t = c.Tiles[xo][yo];
+
+ if (t.Length <= 0)
+ {
+ continue;
+ }
+
+ r = new StaticTile[t.Length];
+
+ for (var i = 0; i < t.Length; i++)
+ {
+ r[i] = t[i];
+ r[i].Z += o.Z;
+ }
+
+ yield return r;
+ }
+ }
+ }
+ }
+
+ public IEnumerable SelectMultiTilesNew(Sector s, Rectangle2D bounds)
+ {
+ List multis = s.Multis;
+
+ for (int l = multis.Count - 1; l >= 0; --l)
+ {
+ if (multis[l] is not { Deleted: false } o)
+ {
+ continue;
+ }
+
+ MultiComponentList c = o.Components;
+
+ int x, y, xo, yo;
+ StaticTile[] t, r;
+
+ for (x = bounds.Start.X; x < bounds.End.X; x++)
+ {
+ xo = x - (o.X + c.Min.X);
+
+ if (xo < 0 || xo >= c.Width)
+ {
+ continue;
+ }
+
+ for (y = bounds.Start.Y; y < bounds.End.Y; y++)
+ {
+ yo = y - (o.Y + c.Min.Y);
+
+ if (yo < 0 || yo >= c.Height)
+ {
+ continue;
+ }
+
+ t = c.Tiles[xo][yo];
+
+ if (t.Length <= 0)
+ {
+ continue;
+ }
+
+ r = new StaticTile[t.Length];
+
+ for (var i = 0; i < t.Length; i++)
+ {
+ r[i] = t[i];
+ r[i].Z += o.Z;
+ }
+
+ yield return r;
+ }
+ }
+ }
+ }
+ }
+
+ public class BItem : IPoint3D, IEntity
+ {
+ public object Parent { get; set; } = null;
+
+ public bool Deleted { get; set; } = false;
+
+ public int Z { get; set; } = 1;
+
+ public int X { get; set; } = 1;
+
+ public int Y { get; set; } = 1;
+
+ public Serial Serial => throw new NotImplementedException();
+
+ public Point3D Location { get; }
+
+ public Map Map { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+
+ public Region Region => throw new NotImplementedException();
+
+ public string Name { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ public int Hue { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ public Direction Direction { get => throw new System.NotImplementedException(); set => throw new NotImplementedException(); }
+ public DateTime Created { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+
+ public int TypeRef => throw new NotImplementedException();
+
+ int IPoint3D.Z => throw new NotImplementedException();
+
+ int IPoint2D.X => throw new NotImplementedException();
+
+ int IPoint2D.Y => throw new NotImplementedException();
+
+ DateTime ISerializable.Created { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ DateTime ISerializable.LastSerialized { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ long ISerializable.SavePosition { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ BufferWriter ISerializable.SaveBuffer { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+
+ int ISerializable.TypeRef => throw new NotImplementedException();
+
+ Serial ISerializable.Serial => throw new NotImplementedException();
+
+ bool ISerializable.Deleted => throw new NotImplementedException();
+
+ public BItem(Point3D location)
+ {
+ Location = location;
+ }
+
+ public void Delete()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void ProcessDelta()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void OnStatsQuery(Server.Mobile m)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void InvalidateProperties()
+ {
+ throw new NotImplementedException();
+ }
+
+ public int CompareTo(object obj)
+ {
+ throw new NotImplementedException();
+ }
+
+ public int CompareTo(IEntity other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void MoveToWorld(Point3D location, Map map)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool InRange(Point2D p, int range)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool InRange(Point3D p, int range)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void RemoveBItem(BItem BItem)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void BeforeSerialize()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Deserialize(IGenericReader reader)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Serialize(IGenericWriter writer)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void SetTypeRef(Type type)
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.BeforeSerialize()
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.Deserialize(IGenericReader reader)
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.Serialize(IGenericWriter writer)
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.Delete()
+ {
+ throw new NotImplementedException();
+ }
+
+ void ISerializable.SetTypeRef(Type type)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void RemoveItem(Item item)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public class BaseMulti : BItem
+ {
+ public MultiComponentList Components = MultiComponentList.Empty;
+
+ public BaseMulti(Point3D location) : base(location)
+ {
+ for (int i = 0; i < 20; ++i)
+ {
+ for (int j = 0; j < 20; ++j)
+ {
+ for (int z = 0; z < 20; ++z)
+ {
+ Components.Add(123, i, j, z);
+ }
+ }
+ }
+ }
+ }
+
+ public class Sector
+ {
+ public List Multis { get; set; } = new List();
+ }
+}
diff --git a/Projects/Benchmarks/Benchmarks/Map/MapSelectors.cs b/Projects/Benchmarks/Benchmarks/Map/MapSelectors.cs
deleted file mode 100644
index 4c47b7189..000000000
--- a/Projects/Benchmarks/Benchmarks/Map/MapSelectors.cs
+++ /dev/null
@@ -1,665 +0,0 @@
-using BenchmarkDotNet.Attributes;
-using BenchmarkDotNet.Jobs;
-using Server;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Benchmarks
-{
- [SimpleJob(RuntimeMoniker.NetCoreApp50)]
- public class MapSelectors
- {
- static readonly Sector sector = new Sector();
- static Server.Rectangle2D bounds = new Server.Rectangle2D(0, 0, 100, 100);
-
- public static void Init()
- {
- for (int i = 0; i < 50; ++i)
- {
- sector.Multis.Add(new BaseMulti());
- }
- for (int i = 0; i < 1000; ++i)
- {
- sector.BItems.Add(new BItem());
- }
- for (int i = 0; i < 1000; ++i)
- {
- sector.Mobiles.Add(new Mobile());
- }
- }
-
- #region MultiTiles
- [Benchmark]
- public void SelectMultiTilesNew()
- {
- foreach(StaticTile[] tiles in SelectMultiTiles(sector, bounds))
- {
- for(int i = 0; i < tiles.Length; ++i)
- {
- int id = tiles[i].ID;
- }
- }
- }
-
- [Benchmark]
- public void SelectMultiTilesLinq()
- {
- foreach(StaticTile[] tiles in SelectMultiTilesLinq(sector, bounds))
- {
- for(int i = 0; i < tiles.Length; ++i)
- {
- int id = tiles[i].ID;
- }
- }
- }
-
- public IEnumerable SelectMultiTilesLinq(Sector s, Server.Rectangle2D bounds)
- {
- foreach (var o in s.Multis.Where(o => o != null && !o.Deleted))
- {
- var c = o.Components;
-
- int x, y, xo, yo;
- StaticTile[] t, r;
-
- for (x = bounds.Start.X; x < bounds.End.X; x++)
- {
- xo = x - (o.X + c.Min.X);
-
- if (xo < 0 || xo >= c.Width)
- {
- continue;
- }
-
- for (y = bounds.Start.Y; y < bounds.End.Y; y++)
- {
- yo = y - (o.Y + c.Min.Y);
-
- if (yo < 0 || yo >= c.Height)
- {
- continue;
- }
-
- t = c.Tiles[xo][yo];
-
- if (t.Length <= 0)
- {
- continue;
- }
-
- r = new StaticTile[t.Length];
-
- for (var i = 0; i < t.Length; i++)
- {
- r[i] = t[i];
- r[i].Z += o.Z;
- }
-
- yield return r;
- }
- }
- }
- }
-
- public IEnumerable SelectMultiTiles(Sector s, Server.Rectangle2D bounds)
- {
- for (int l = s.Multis.Count - 1; l >= 0; --l)
- {
- BaseMulti o = s.Multis[l];
- if (o != null && !o.Deleted)
- {
- MultiComponentList c = o.Components;
-
- int x, y, xo, yo;
- StaticTile[] t, r;
-
- for (x = bounds.Start.X; x < bounds.End.X; x++)
- {
- xo = x - (o.X + c.Min.X);
-
- if (xo < 0 || xo >= c.Width)
- {
- continue;
- }
-
- for (y = bounds.Start.Y; y < bounds.End.Y; y++)
- {
- yo = y - (o.Y + c.Min.Y);
-
- if (yo < 0 || yo >= c.Height)
- {
- continue;
- }
-
- t = c.Tiles[xo][yo];
-
- if (t.Length <= 0)
- {
- continue;
- }
-
- r = new StaticTile[t.Length];
-
- for (var i = 0; i < t.Length; i++)
- {
- r[i] = t[i];
- r[i].Z += o.Z;
- }
-
- yield return r;
- }
- }
- }
- }
- }
-
- #endregion
-
- #region Multis
- [Benchmark]
- public void SelectMultisNew()
- {
- SelectMultis(sector, bounds);
- }
-
- [Benchmark]
- public void SelectMultisLinq()
- {
- SelectMultisLinq(sector, bounds);
- }
-
- public IEnumerable SelectMultisLinq(Sector s, Server.Rectangle2D bounds)
- {
- return s.Multis.Where(o => o != null && !o.Deleted && bounds.Contains(o.Location));
- }
-
- public IEnumerable SelectMultis(Sector s, Server.Rectangle2D bounds)
- {
- List entities = new List(s.Multis.Count);
- for (int i = s.Multis.Count - 1; i >= 0; --i)
- {
- BaseMulti BItem = s.Multis[i];
- if (BItem != null && !BItem.Deleted && bounds.Contains(BItem.Location))
- entities.Add(BItem);
- }
- return entities;
- }
- #endregion
-
- #region BItems
- [Benchmark]
- public void SelectBItemsNew()
- {
- SelectBItems(sector, bounds);
- }
-
- [Benchmark]
- public void SelectBItemsLinq()
- {
- SelectBItemsLinq(sector, bounds);
- }
-
- public IEnumerable SelectBItemsLinq(Sector s, Server.Rectangle2D bounds) where T : BItem
- {
- return s.BItems.OfType().Where(o => o != null && !o.Deleted && o.Parent == null && bounds.Contains(o.Location));
- }
-
- public IEnumerable SelectBItems(Sector s, Server.Rectangle2D bounds) where T : BItem
- {
- List entities = new List(s.BItems.Count);
- Type type = typeof(T);
- for (int i = s.BItems.Count - 1; i >= 0; --i)
- {
- BItem BItem = s.BItems[i];
- if (BItem != null && !BItem.Deleted && BItem.Parent == null && bounds.Contains(BItem.Location) && type.IsAssignableFrom(BItem.GetType()))
- entities.Add(BItem as T);
- }
- return entities;
- }
- #endregion
-
- #region Mobiles
- [Benchmark]
- public void SelectMobilesNew()
- {
- SelectMobiles(sector, bounds);
- }
-
- [Benchmark]
- public void SelectMobilesLinq()
- {
- SelectMobilesLinq(sector, bounds);
- }
-
- public IEnumerable SelectMobilesLinq(Sector s, Server.Rectangle2D bounds) where T : Mobile
- {
- return s.Mobiles.OfType().Where(o => o != null && !o.Deleted && bounds.Contains(o.Location));
- }
-
- public IEnumerable SelectMobiles(Sector s, Server.Rectangle2D bounds) where T : Mobile
- {
- List entities = new List(s.Mobiles.Count);
- Type type = typeof(T);
- for (int i = s.Mobiles.Count - 1; i >= 0; --i)
- {
- Mobile mob = s.Mobiles[i];
- if (mob != null && !mob.Deleted && bounds.Contains(mob.Location) && type.IsAssignableFrom(mob.GetType()))
- entities.Add(mob as T);
- }
- return entities;
- }
- #endregion
-
- #region Entities
- [Benchmark]
- public void SelectEntitiesNew()
- {
- SelectEntities(sector, bounds);
- }
-
- [Benchmark]
- public void SelectEntitiesLinq()
- {
- SelectEntitiesLinq(sector, bounds);
- }
-
- public IEnumerable SelectEntitiesLinq(Sector s, Server.Rectangle2D bounds)
- {
- return Enumerable.Empty()
- .Union(s.Mobiles.Where(o => o != null && !o.Deleted))
- .Union(s.BItems.Where(o => o != null && !o.Deleted && o.Parent == null))
- .Where(o => bounds.Contains(o.Location));
- }
-
- private readonly List entities = new (10);
- public IEnumerable SelectEntities(Sector s, Server.Rectangle2D bounds)
- {
- entities.Clear();
- entities.Capacity = s.Mobiles.Count + s.BItems.Count;
- for (int i = s.Mobiles.Count - 1, j = s.BItems.Count - 1; i >= 0 || j >= 0; --i, --j)
- {
- if (j >= 0)
- {
- BItem BItem = s.BItems[j];
- if (BItem != null && !BItem.Deleted && BItem.Parent == null && bounds.Contains(BItem.Location))
- entities.Add(BItem);
- }
- if (i >= 0)
- {
- Mobile mob = s.Mobiles[i];
- if (mob != null && !mob.Deleted && bounds.Contains(mob.Location))
- entities.Add(mob);
- }
- }
- return entities;
- }
- #endregion
- }
- public class BItem : Server.IPoint3D, IEntity
- {
- public object Parent { get; set; } = null;
-
- public bool Deleted { get; set; } = false;
-
- public int Z { get; set; } = 1;
-
- public int X { get; set; } = 1;
-
- public int Y { get; set; } = 1;
-
- public Serial Serial => throw new System.NotImplementedException();
-
- public Point3D Location { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
- public Map Map { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
-
- public Region Region => throw new System.NotImplementedException();
-
- public string Name { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
- public int Hue { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
- public Direction Direction { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
- public DateTime Created { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
-
- public int TypeRef => throw new NotImplementedException();
-
- Point3D IEntity.Location => throw new NotImplementedException();
-
- Map IEntity.Map => throw new NotImplementedException();
-
- int IPoint3D.Z => throw new NotImplementedException();
-
- int IPoint2D.X => throw new NotImplementedException();
-
- int IPoint2D.Y => throw new NotImplementedException();
-
- DateTime ISerializable.Created { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
- DateTime ISerializable.LastSerialized { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
- long ISerializable.SavePosition { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
- BufferWriter ISerializable.SaveBuffer { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
-
- int ISerializable.TypeRef => throw new NotImplementedException();
-
- Serial ISerializable.Serial => throw new NotImplementedException();
-
- bool ISerializable.Deleted => throw new NotImplementedException();
-
- public BItem()
- {
-
- }
-
- public void Delete()
- {
- throw new System.NotImplementedException();
- }
-
- public void ProcessDelta()
- {
- throw new System.NotImplementedException();
- }
-
- public void OnStatsQuery(Server.Mobile m)
- {
- throw new System.NotImplementedException();
- }
-
- public void InvalidateProperties()
- {
- throw new System.NotImplementedException();
- }
-
- public int CompareTo(object obj)
- {
- throw new System.NotImplementedException();
- }
-
- public int CompareTo(IEntity other)
- {
- throw new System.NotImplementedException();
- }
-
- public void MoveToWorld(Point3D location, Map map)
- {
- throw new NotImplementedException();
- }
-
- public bool InRange(Point2D p, int range)
- {
- throw new NotImplementedException();
- }
-
- public bool InRange(Point3D p, int range)
- {
- throw new NotImplementedException();
- }
-
- public void RemoveBItem(BItem BItem)
- {
- throw new NotImplementedException();
- }
-
- public void BeforeSerialize()
- {
- throw new NotImplementedException();
- }
-
- public void Deserialize(IGenericReader reader)
- {
- throw new NotImplementedException();
- }
-
- public void Serialize(IGenericWriter writer)
- {
- throw new NotImplementedException();
- }
-
- public void SetTypeRef(Type type)
- {
- throw new NotImplementedException();
- }
-
- void IEntity.MoveToWorld(Point3D location, Map map)
- {
- throw new NotImplementedException();
- }
-
- void IEntity.ProcessDelta()
- {
- throw new NotImplementedException();
- }
-
- bool IEntity.InRange(Point2D p, int range)
- {
- throw new NotImplementedException();
- }
-
- bool IEntity.InRange(Point3D p, int range)
- {
- throw new NotImplementedException();
- }
-
- void ISerializable.BeforeSerialize()
- {
- throw new NotImplementedException();
- }
-
- void ISerializable.Deserialize(IGenericReader reader)
- {
- throw new NotImplementedException();
- }
-
- void ISerializable.Serialize(IGenericWriter writer)
- {
- throw new NotImplementedException();
- }
-
- void ISerializable.Delete()
- {
- throw new NotImplementedException();
- }
-
- void ISerializable.SetTypeRef(Type type)
- {
- throw new NotImplementedException();
- }
-
- public void RemoveItem(Item item)
- {
- throw new NotImplementedException();
- }
- }
-
- public class Mobile : Server.IPoint3D, IEntity
- {
- public bool Deleted { get; set; } = false;
-
- public int Z { get; set; } = 1;
-
- public int X { get; set; } = 1;
-
- public int Y { get; set; } = 1;
-
- public Serial Serial => throw new System.NotImplementedException();
-
- public Point3D Location { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
- public Map Map { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
-
- public Region Region => throw new System.NotImplementedException();
-
- public string Name { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
- public int Hue { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
- public Direction Direction { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
- public DateTime Created { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
-
- public int TypeRef => throw new NotImplementedException();
-
- Point3D IEntity.Location => throw new NotImplementedException();
-
- Map IEntity.Map => throw new NotImplementedException();
-
- int IPoint3D.Z => throw new NotImplementedException();
-
- int IPoint2D.X => throw new NotImplementedException();
-
- int IPoint2D.Y => throw new NotImplementedException();
-
- DateTime ISerializable.Created { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
- DateTime ISerializable.LastSerialized { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
- long ISerializable.SavePosition { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
- BufferWriter ISerializable.SaveBuffer { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
-
- int ISerializable.TypeRef => throw new NotImplementedException();
-
- Serial ISerializable.Serial => throw new NotImplementedException();
-
- bool ISerializable.Deleted => throw new NotImplementedException();
-
- public Mobile()
- {
-
- }
-
- public void Delete()
- {
- throw new System.NotImplementedException();
- }
-
- public void ProcessDelta()
- {
- throw new System.NotImplementedException();
- }
-
- public void OnStatsQuery(Server.Mobile m)
- {
- throw new System.NotImplementedException();
- }
-
- public void InvalidateProperties()
- {
- throw new System.NotImplementedException();
- }
-
- public int CompareTo(object obj)
- {
- throw new System.NotImplementedException();
- }
-
- public int CompareTo(IEntity other)
- {
- throw new System.NotImplementedException();
- }
-
- public void MoveToWorld(Point3D location, Map map)
- {
- throw new NotImplementedException();
- }
-
- public bool InRange(Point2D p, int range)
- {
- throw new NotImplementedException();
- }
-
- public bool InRange(Point3D p, int range)
- {
- throw new NotImplementedException();
- }
-
- public void RemoveBItem(BItem BItem)
- {
- throw new NotImplementedException();
- }
-
- public void BeforeSerialize()
- {
- throw new NotImplementedException();
- }
-
- public void Deserialize(IGenericReader reader)
- {
- throw new NotImplementedException();
- }
-
- public void Serialize(IGenericWriter writer)
- {
- throw new NotImplementedException();
- }
-
- public void SetTypeRef(Type type)
- {
- throw new NotImplementedException();
- }
-
- void IEntity.MoveToWorld(Point3D location, Map map)
- {
- throw new NotImplementedException();
- }
-
- void IEntity.ProcessDelta()
- {
- throw new NotImplementedException();
- }
-
- bool IEntity.InRange(Point2D p, int range)
- {
- throw new NotImplementedException();
- }
-
- bool IEntity.InRange(Point3D p, int range)
- {
- throw new NotImplementedException();
- }
-
- void ISerializable.BeforeSerialize()
- {
- throw new NotImplementedException();
- }
-
- void ISerializable.Deserialize(IGenericReader reader)
- {
- throw new NotImplementedException();
- }
-
- void ISerializable.Serialize(IGenericWriter writer)
- {
- throw new NotImplementedException();
- }
-
- void ISerializable.Delete()
- {
- throw new NotImplementedException();
- }
-
- void ISerializable.SetTypeRef(Type type)
- {
- throw new NotImplementedException();
- }
-
- public void RemoveItem(Item item)
- {
- throw new NotImplementedException();
- }
- }
-
- public class BaseMulti : BItem
- {
- public MultiComponentList Components = MultiComponentList.Empty;
-
- public BaseMulti()
- {
- for (int i = 0; i < 20; ++i)
- for (int j = 0; j < 20; ++j)
- for (int z = 0; z < 20; ++z)
- Components.Add(123, i, j, z);
- }
-
- }
-
- public class Sector
- {
- public List BItems { get; set; } = new List();
- public List Mobiles { get; set; } = new List();
- public List Multis { get; set; } = new List();
- }
-}
diff --git a/Projects/Benchmarks/Program.cs b/Projects/Benchmarks/Program.cs
index bfdadb1bc..e86c18d19 100644
--- a/Projects/Benchmarks/Program.cs
+++ b/Projects/Benchmarks/Program.cs
@@ -1,5 +1,9 @@
using BenchmarkDotNet.Running;
-using Benchmarks.Benchmarks.Rng;
+using Benchmarks.EntitiesSelectors;
+using Benchmarks.ItemSelectors;
+using Benchmarks.MobileSelectors;
+using Benchmarks.MultiSelectors;
+using Benchmarks.MultiTilesSelectors;
namespace Benchmarks
{
@@ -15,10 +19,14 @@ namespace Benchmarks
// var textEncoding = BenchmarkRunner.Run();
// var logging = BenchmarkRunner.Run();
// var gumpPacket = BenchmarkRunner.Run();
- // MapSelectors.Init();
- // var mapSelectors = BenchmarkRunner.Run();
// var rngTest = BenchmarkRunner.Run();
- var doubleRngText = BenchmarkRunner.Run();
+ //var doubleRngText = BenchmarkRunner.Run();
+
+ //var mapEntitiesSelectors = BenchmarkRunner.Run();
+ //var mapMobilesSelectors = BenchmarkRunner.Run();
+ //var mapMultiTilesSelectors = BenchmarkRunner.Run();
+ //var mapMultiSelectors = BenchmarkRunner.Run();
+ var mapItemsSelectors = BenchmarkRunner.Run();
}
}
}