Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add compreg methods to entitymanager #5655

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ END TEMPLATE-->

### New features

*None yet*
* Add EntityManager overloads for ComponentRegistration that's faster than the generic methods.

### Bugfixes

Expand Down
96 changes: 96 additions & 0 deletions Robust.Benchmarks/EntityManager/HasComponentBenchmark.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Engines;
using JetBrains.Annotations;
using Robust.Shared.Analyzers;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.UnitTesting.Server;

namespace Robust.Benchmarks.EntityManager;

[Virtual]
public partial class HasComponentBenchmark
{
private static readonly Consumer Consumer = new();

private ISimulation _simulation = default!;
private IEntityManager _entityManager = default!;

private ComponentRegistration _compReg = default!;

private A _dummyA = new();

[UsedImplicitly]
[Params(1, 10, 100, 1000)]
public int N;

[GlobalSetup]
public void GlobalSetup()
{
_simulation = RobustServerSimulation
.NewSimulation()
.RegisterComponents(f => f.RegisterClass<A>())
.InitializeInstance();

_entityManager = _simulation.Resolve<IEntityManager>();
var map = _simulation.CreateMap().Uid;
var coords = new EntityCoordinates(map, default);
_compReg = _entityManager.ComponentFactory.GetRegistration(typeof(A));

for (var i = 0; i < N; i++)
{
var uid = _entityManager.SpawnEntity(null, coords);
_entityManager.AddComponent<A>(uid);
}
}

[Benchmark]
public void HasComponentGeneric()
{
for (var i = 2; i <= N+1; i++)
{
var uid = new EntityUid(i);
var result = _entityManager.HasComponent<A>(uid);
Consumer.Consume(result);
}
}

[Benchmark]
public void HasComponentCompReg()
{
for (var i = 2; i <= N+1; i++)
{
var uid = new EntityUid(i);
var result = _entityManager.HasComponent(uid, _compReg);
Consumer.Consume(result);
}
}

[Benchmark]
public void HasComponentType()
{
for (var i = 2; i <= N+1; i++)
{
var uid = new EntityUid(i);
var result = _entityManager.HasComponent(uid, typeof(A));
Consumer.Consume(result);
}
}

[Benchmark]
public void HasComponentGetType()
{
for (var i = 2; i <= N+1; i++)
{
var uid = new EntityUid(i);
var type = _dummyA.GetType();
var result = _entityManager.HasComponent(uid, type);
Consumer.Consume(result);
}
}

[ComponentProtoName("A")]
public sealed partial class A : Component
{
}
}
61 changes: 54 additions & 7 deletions Robust.Shared/GameObjects/EntityManager.Components.cs
Original file line number Diff line number Diff line change
Expand Up @@ -197,17 +197,23 @@ public void AddComponents(EntityUid target, ComponentRegistry registry, bool rem
{
var reg = _componentFactory.GetRegistration(name);

if (HasComponent(target, reg.Type))
if (removeExisting)
{
if (!removeExisting)
var comp = _componentFactory.GetComponent(reg);
_serManager.CopyTo(entry.Component, ref comp, notNullableOverride: true);
AddComponentInternal(target, comp, reg, overwrite: true, metadata: metadata);
}
else
{
if (HasComponent(target, reg))
{
continue;
}

RemoveComponent(target, reg.Type, metadata);
var comp = _componentFactory.GetComponent(reg);
_serManager.CopyTo(entry.Component, ref comp, notNullableOverride: true);
AddComponentInternal(target, comp, reg, overwrite: false, metadata: metadata);
}

var comp = _componentFactory.GetComponent(reg);
_serManager.CopyTo(entry.Component, ref comp, notNullableOverride: true);
AddComponent(target, comp, metadata: metadata);
}
}

Expand Down Expand Up @@ -315,6 +321,22 @@ public void AddComponent<T>(EntityUid uid, T component, bool overwrite = false,
AddComponentInternal(uid, component, overwrite, false, metadata);
}

private void AddComponentInternal<T>(
EntityUid uid,
T component,
ComponentRegistration compReg,
bool overwrite = false,
MetaDataComponent? metadata = null) where T : IComponent
{
if (!MetaQuery.Resolve(uid, ref metadata, false))
throw new ArgumentException($"Entity {uid} is not valid.", nameof(uid));

DebugTools.Assert(component.Owner == default);
component.Owner = uid;

AddComponentInternal(uid, component, compReg, overwrite, skipInit: false, metadata);
}

private void AddComponentInternal<T>(EntityUid uid, T component, bool overwrite, bool skipInit, MetaDataComponent? metadata) where T : IComponent
{
if (!MetaQuery.ResolveInternal(uid, ref metadata, false))
Expand Down Expand Up @@ -731,6 +753,14 @@ public bool HasComponent<T>([NotNullWhen(true)] EntityUid? uid) where T : ICompo
return uid.HasValue && HasComponent<T>(uid.Value);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Pure]
public bool HasComponent(EntityUid uid, ComponentRegistration reg)
{
var dict = _entTraitArray[reg.Idx.Value];
return dict.TryGetValue(uid, out var comp) && !comp.Deleted;
}

/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Pure]
Expand Down Expand Up @@ -943,6 +973,23 @@ public bool TryGetComponent<T>([NotNullWhen(true)] EntityUid? uid, [NotNullWhen(
return false;
}

/// <inheritdoc />
public bool TryGetComponent(EntityUid uid, ComponentRegistration reg, [NotNullWhen(true)] out IComponent? component)
{
var dict = _entTraitArray[reg.Idx.Value];
if (dict.TryGetValue(uid, out var comp))
{
if (!comp.Deleted)
{
component = comp;
return true;
}
}

component = null;
return false;
}

/// <inheritdoc />
public bool TryGetComponent(EntityUid uid, Type type, [NotNullWhen(true)] out IComponent? component)
{
Expand Down
17 changes: 17 additions & 0 deletions Robust.Shared/GameObjects/IEntityManager.Components.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,14 @@ public partial interface IEntityManager
/// <returns>True if the entity has the component type, otherwise false.</returns>
bool HasComponent<T>([NotNullWhen(true)] EntityUid? uid) where T : IComponent;

/// <summary>
/// Checks if the entity has a component type.
/// </summary>
/// <param name="uid">Entity UID to check.</param>
/// <param name="reg">The component registration to check for.</param>
/// <returns>True if the entity has the component type, otherwise false.</returns>
bool HasComponent(EntityUid uid, ComponentRegistration reg);

/// <summary>
/// Checks if the entity has a component type.
/// </summary>
Expand Down Expand Up @@ -294,6 +302,15 @@ public partial interface IEntityManager
/// <returns>If the component existed in the entity.</returns>
bool TryGetComponent<T>([NotNullWhen(true)] EntityUid? uid, [NotNullWhen(true)] out T? component) where T : IComponent?;

/// <summary>
/// Returns the component of a specific type.
/// </summary>
/// <param name="uid">Entity UID to check.</param>
/// <param name="reg">The component registration to check for.</param>
/// <param name="component">Component of the specified type (if exists).</param>
/// <returns>If the component existed in the entity.</returns>
bool TryGetComponent(EntityUid uid, ComponentRegistration reg, [NotNullWhen(true)] out IComponent? component);

/// <summary>
/// Returns the component of a specific type.
/// </summary>
Expand Down
Loading