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(); } } }