From df3c876b58bcb6e151288d3f8e18b00b178a76fb Mon Sep 17 00:00:00 2001
From: ztw <412467438@qq.com>
Date: Mon, 24 Aug 2026 16:56:28 +0800
Subject: [PATCH] - Use CollectionsMarshal.GetValueRefOrAddDefault for single
hash lookup (.NET 6+) - Add Query.CountEntities() for allocation-free entity
counting"
---
src/Arch/Core/Query.cs | 17 +++++++++++++++++
src/Arch/Core/World.cs | 21 +++++++++++++++++----
2 files changed, 34 insertions(+), 4 deletions(-)
diff --git a/src/Arch/Core/Query.cs b/src/Arch/Core/Query.cs
index feed4a1e..6b8359b5 100644
--- a/src/Arch/Core/Query.cs
+++ b/src/Arch/Core/Query.cs
@@ -1,3 +1,4 @@
+using System.Diagnostics.Contracts;
using Arch.Core.Extensions;
using Arch.Core.Extensions.Internal;
using Arch.Core.Utils;
@@ -571,6 +572,22 @@ internal Query(Archetypes allArchetypes, QueryDescription description)
_queryDescription = description;
}
+ ///
+ /// Counts all s that match this query.
+ ///
+ [Pure]
+ public int CountEntities()
+ {
+ var counter = 0;
+ foreach (var archetype in GetArchetypeIterator())
+ {
+ var entities = archetype.EntityCount;
+ counter += entities;
+ }
+
+ return counter;
+ }
+
///
/// Checks whether the specified matches.
///
diff --git a/src/Arch/Core/World.cs b/src/Arch/Core/World.cs
index 82c6a5ab..38c5b062 100644
--- a/src/Arch/Core/World.cs
+++ b/src/Arch/Core/World.cs
@@ -410,17 +410,30 @@ public void Destroy(Entity entity)
[Pure]
public Query Query(in QueryDescription queryDescription)
{
- // Looping over all archetypes, their chunks and their entities.
- var queryCache = QueryCache; // Storing locally to only access the QueryCache once
+ var queryCache = QueryCache; // Store locally to only access the field once
+
+ #if NET6_0_OR_GREATER
+ ref var queryRef = ref CollectionsMarshal.GetValueRefOrAddDefault(queryCache, queryDescription, out bool exists);
+ if (exists)
+ {
+ return queryRef!;
+ }
+ else
+ {
+ var newQuery = new Query(Archetypes, queryDescription);
+ queryRef = newQuery;
+ return newQuery;
+ }
+ #else
if (queryCache.TryGetValue(queryDescription, out var query))
{
return query;
}
query = new Query(Archetypes, queryDescription);
- queryCache[queryDescription] = query;
-
+ queryCache.Add(queryDescription, query);
return query;
+ #endif
}
///