Refactored map selector benchmarks (#914)

This commit is contained in:
Stefano Merotta 2022-01-08 07:42:37 +01:00 committed by GitHub
parent 2f13dfebed
commit 51169ddbb0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 1880 additions and 669 deletions

View file

@ -10,6 +10,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
<PackageReference Include="NetFabric.Hyperlinq" Version="3.0.0-beta48" />
<PackageReference Include="StructLinq" Version="0.27.0" />
<ProjectReference Include="..\Server\Server.csproj" />
<ProjectReference Include="..\UOContent\UOContent.csproj" />
</ItemGroup>

View file

@ -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<IEntity> SelectEntitiesLinq(Sector s, Rectangle2D bounds)
{
return Enumerable.Empty<IEntity>()
.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<IEntity> entities = new(10);
public IEnumerable<IEntity> 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<IEntity> SelectEntitiesHyperlinq(Sector s, Rectangle2D bounds)
{
ArraySegmentWhereSelectEnumerable<Mobile, IEntity, MobileWhereHyper, SelectHyper<Mobile, IEntity>> mobiles =
s.Mobiles.AsValueEnumerable().Where(new MobileWhereHyper(bounds)).Select<IEntity, SelectHyper<Mobile, IEntity>>();
ArraySegmentWhereSelectEnumerable<BItem, IEntity, BItemWhereHyper, SelectHyper<BItem, IEntity>> items =
s.BItems.AsValueEnumerable().Where(new BItemWhereHyper(bounds)).Select<IEntity, SelectHyper<BItem, IEntity>>();
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<BItem> BItems { get; set; } = new List<BItem>();
public List<Mobile> Mobiles { get; set; } = new List<Mobile>();
}
public struct BItemWhereHyper : NetFabric.Hyperlinq.IFunction<BItem, bool>
{
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<Mobile, bool>
{
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<TSource, TDest> : NetFabric.Hyperlinq.IFunction<TSource, TDest> where TSource : TDest
{
public TDest Invoke(TSource arg)
{
return arg;
}
}
}

View file

@ -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<BItemDerived>(sector, bounds))
{
toRet = i;
}
return toRet;
}
[Benchmark]
public BItemDerived SelectBItemsLinq()
{
BItemDerived toRet = null;
foreach (BItemDerived i in SelectBItemsLinq<BItemDerived>(sector, bounds))
{
toRet = i;
}
return toRet;
}
[Benchmark]
public BItemDerived SelectBItemsLinqStruct()
{
BItemDerived toRet = null;
foreach (BItemDerived i in SelectBItemsLinqStruct<BItemDerived>(sector, bounds))
{
toRet = i;
}
return toRet;
}
[Benchmark]
public BItemDerived SelectBItemsLinqStructInterface()
{
BItemDerived toRet = null;
IEnumerable<BItemDerived> enumerable = SelectBItemsLinqStruct<BItemDerived>(sector, bounds).ToEnumerable();
foreach (BItemDerived i in enumerable)
{
toRet = i;
}
return toRet;
}
[Benchmark]
public BItemDerived SelectBItemsHyperLinq()
{
BItemDerived toRet = null;
foreach (BItemDerived i in SelectBItemsHyperlinq<BItemDerived>(sector, bounds))
{
toRet = i;
}
return toRet;
}
[Benchmark]
public BItemDerived SelectBItemsHyperLinqInterface()
{
BItemDerived toRet = null;
IEnumerable<BItemDerived> enumerable = SelectBItemsHyperlinq<BItemDerived>(sector, bounds);
foreach (BItemDerived i in enumerable)
{
toRet = i;
}
return toRet;
}
[Benchmark]
public BItemDerived SelectBItemsHyperLinqArrayPool()
{
BItemDerived toRet = null;
using Lease<BItemDerived> lease = SelectBItemsHyperlinq<BItemDerived>(sector, bounds).ToArray(ArrayPool<BItemDerived>.Shared);
foreach (BItemDerived i in lease)
{
toRet = i;
}
return toRet;
}
public IEnumerable<T> SelectBItemsLinq<T>(Sector s, Rectangle2D bounds) where T : BItem
{
return s.BItems.OfType<T>().Where(o => o is { Deleted: false, Parent: null } && bounds.Contains(o.Location));
}
public IEnumerable<T> SelectBItems<T>(Sector s, Rectangle2D bounds) where T : BItem
{
List<BItem> items = s.BItems;
List<T> 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<BItem, T, WhereEnumerable<BItem, ListEnumerable<BItem>, ArrayStructEnumerator<BItem>, BItemWhere<T>>,
WhereEnumerator<BItem, ArrayStructEnumerator<BItem>, BItemWhere<T>>, BItemSelect<T>>
SelectBItemsLinqStruct<T>(Sector s, Rectangle2D bounds) where T : BItem
{
BItemWhere<T> bitemWhere = new(bounds);
BItemSelect<T> bitemSelect = new();
return s.BItems.ToStructEnumerable()
.Where(ref bitemWhere, x => x)
.Select(ref bitemSelect, x => x, x => x);
}
public ArraySegmentWhereSelectEnumerable<BItem, T, BItemWhereHyper<T>, SelectHyper<BItem, T>>
SelectBItemsHyperlinq<T>(Sector s, Rectangle2D bounds) where T : BItem
{
return s.BItems.AsValueEnumerable()
.Where(new BItemWhereHyper<T>(bounds))
.Select<T, SelectHyper<BItem, T>>();
}
}
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<BItem> BItems { get; set; } = new List<BItem>();
}
public struct BItemWhere<T> : StructLinq.IFunction<BItem, bool> 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<T> : StructLinq.IFunction<BItem, T> where T : BItem
{
public T Eval(BItem element)
{
return (T)element;
}
}
public struct BItemWhereHyper<T> : NetFabric.Hyperlinq.IFunction<BItem, bool> 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<TSource, TDest> : NetFabric.Hyperlinq.IFunction<TSource, TDest> where TDest : TSource
{
public TDest Invoke(TSource arg)
{
return (TDest)arg;
}
}
}

View file

@ -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<MobileDerived>(sector, bounds))
{
toRet = m;
}
return toRet;
}
[Benchmark]
public MobileDerived SelectMobilesLinq()
{
MobileDerived toRet = null;
foreach (MobileDerived m in SelectMobilesLinq<MobileDerived>(sector, bounds))
{
toRet = m;
}
return toRet;
}
[Benchmark]
public MobileDerived SelectMobilesHyperLinq()
{
MobileDerived toRet = null;
foreach (MobileDerived m in SelectMobilesHyperlinq<MobileDerived>(sector, bounds))
{
toRet = m;
}
return toRet;
}
public IEnumerable<T> SelectMobilesLinq<T>(Sector s, Rectangle2D bounds) where T : Mobile
{
return s.Mobiles.OfType<T>().Where(o => o is { Deleted: false } && bounds.Contains(o.Location));
}
public IEnumerable<T> SelectMobiles<T>(Sector s, Rectangle2D bounds) where T : Mobile
{
List<Mobile> mobiles = s.Mobiles;
List<T> 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<Mobile, T, MobileWhereHyper<T>, SelectHyper<Mobile, T>>
SelectMobilesHyperlinq<T>(Sector s, Rectangle2D bounds) where T : Mobile
{
return s.Mobiles.AsValueEnumerable()
.Where(new MobileWhereHyper<T>(bounds))
.Select<T, SelectHyper<Mobile, T>>();
}
}
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<Mobile> Mobiles { get; set; } = new List<Mobile>();
}
public struct MobileWhereHyper<T> : NetFabric.Hyperlinq.IFunction<Mobile, bool> 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<TSource, TDest> : NetFabric.Hyperlinq.IFunction<TSource, TDest> where TDest : TSource
{
public TDest Invoke(TSource arg)
{
return (TDest)arg;
}
}
}

View file

@ -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<BaseMulti> SelectMultiLinq(Sector s, Rectangle2D bounds)
{
return s.Multis.Where(o => o is { Deleted: false } && bounds.Contains(o.Location));
}
public IEnumerable<BaseMulti> SelectMultiNew(Sector s, Rectangle2D bounds)
{
List<BaseMulti> 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<BaseMulti, MultiWhereHyper>
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<BaseMulti> Multis { get; set; } = new List<BaseMulti>();
}
public struct MultiWhereHyper : NetFabric.Hyperlinq.IFunction<BaseMulti, bool>
{
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);
}
}
}

View file

@ -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<StaticTile[]> 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<StaticTile[]> SelectMultiTilesNew(Sector s, Rectangle2D bounds)
{
List<BaseMulti> 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<BaseMulti> Multis { get; set; } = new List<BaseMulti>();
}
}

View file

@ -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<StaticTile[]> 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<StaticTile[]> 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<BaseMulti> SelectMultisLinq(Sector s, Server.Rectangle2D bounds)
{
return s.Multis.Where(o => o != null && !o.Deleted && bounds.Contains(o.Location));
}
public IEnumerable<BaseMulti> SelectMultis(Sector s, Server.Rectangle2D bounds)
{
List<BaseMulti> entities = new List<BaseMulti>(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<BItem>(sector, bounds);
}
[Benchmark]
public void SelectBItemsLinq()
{
SelectBItemsLinq<BItem>(sector, bounds);
}
public IEnumerable<T> SelectBItemsLinq<T>(Sector s, Server.Rectangle2D bounds) where T : BItem
{
return s.BItems.OfType<T>().Where(o => o != null && !o.Deleted && o.Parent == null && bounds.Contains(o.Location));
}
public IEnumerable<T> SelectBItems<T>(Sector s, Server.Rectangle2D bounds) where T : BItem
{
List<T> entities = new List<T>(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<Mobile>(sector, bounds);
}
[Benchmark]
public void SelectMobilesLinq()
{
SelectMobilesLinq<Mobile>(sector, bounds);
}
public IEnumerable<T> SelectMobilesLinq<T>(Sector s, Server.Rectangle2D bounds) where T : Mobile
{
return s.Mobiles.OfType<T>().Where(o => o != null && !o.Deleted && bounds.Contains(o.Location));
}
public IEnumerable<T> SelectMobiles<T>(Sector s, Server.Rectangle2D bounds) where T : Mobile
{
List<T> entities = new List<T>(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<Server.IEntity> SelectEntitiesLinq(Sector s, Server.Rectangle2D bounds)
{
return Enumerable.Empty<IEntity>()
.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<Server.IEntity> entities = new (10);
public IEnumerable<Server.IEntity> 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<BItem> BItems { get; set; } = new List<BItem>();
public List<Mobile> Mobiles { get; set; } = new List<Mobile>();
public List<BaseMulti> Multis { get; set; } = new List<BaseMulti>();
}
}

View file

@ -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<BenchmarkTextEncoding>();
// var logging = BenchmarkRunner.Run<BenchmarkConsoleLogging>();
// var gumpPacket = BenchmarkRunner.Run<OutgoingGumpPacketBenchmarks>();
// MapSelectors.Init();
// var mapSelectors = BenchmarkRunner.Run<MapSelectors>();
// var rngTest = BenchmarkRunner.Run<BenchmarkXoshiro>();
var doubleRngText = BenchmarkRunner.Run<BenchmarkDoubleVsFixed>();
//var doubleRngText = BenchmarkRunner.Run<BenchmarkDoubleVsFixed>();
//var mapEntitiesSelectors = BenchmarkRunner.Run<MapEntitiesSelectors>();
//var mapMobilesSelectors = BenchmarkRunner.Run<MapMobileSelectors>();
//var mapMultiTilesSelectors = BenchmarkRunner.Run<MapMultiTilesSelectors>();
//var mapMultiSelectors = BenchmarkRunner.Run<MapMultiSelectors>();
var mapItemsSelectors = BenchmarkRunner.Run<MapItemSelectors>();
}
}
}